package leigh.graphql;

import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import graphql.schema.idl.*;
import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import static graphql.schema.idl.TypeRuntimeWiring.newTypeWiring;

public class Example {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(Example.class);
    private DataFetchers graphQLDataFetchers = new DataFetchers();
    private GraphQL graphQL;

    public static void main(String[] args) throws IOException {
        new Example();
    }

    public Example() throws IOException {
        try (InputStream is = Example.class.getResourceAsStream("/schema.graphqls")) {
            String sdl = IOUtils.toString(is, Charset.defaultCharset());
            GraphQLSchema graphQLSchema = buildSchema(sdl);
            this.graphQL = GraphQL.newGraphQL(graphQLSchema).build();
        }

        ExecutionResult er = this.graphQL.execute("{\n" +
                "  bookById(id: \"book-1\"){\n" +
                "    id\n" +
                "    name\n" +
                "    author {\n" +
                "      firstName\n" +
                "      lastName\n" +
                "    }\n" +
                "  }\n" +
                "}");
        logger.info("ER: {}", er);

        er = this.graphQL.execute("{\n" +
                "  allBooks {\n" +
                "    id\n" +
                "    name\n" +
                "  }\n" +
                "}");
        logger.info("ER: {}", er);

        er = this.graphQL.execute("mutation {hello(name:\"Alex\")}");
        logger.info("ER: {}", er);

        er = this.graphQL.execute("mutation {bad(name:\"Alex\")}");
        logger.info("ER: {}", er);
    }

    private GraphQLSchema buildSchema(String sdl) {
        TypeDefinitionRegistry typeRegistry = new SchemaParser().parse(sdl);
        RuntimeWiring runtimeWiring = buildWiring();
        SchemaGenerator schemaGenerator = new SchemaGenerator();
        return schemaGenerator.makeExecutableSchema(typeRegistry, runtimeWiring);
    }

    // In the GraphQLProvider class
    private RuntimeWiring buildWiring() {
        return RuntimeWiring.newRuntimeWiring()
                .type(newTypeWiring("Query")
                        .dataFetcher("bookById", graphQLDataFetchers.getBookByIdDataFetcher())
                        .dataFetcher("allBooks", graphQLDataFetchers.getAllBooks()))
                .type(newTypeWiring("Book")
                        .dataFetcher("author", graphQLDataFetchers.getAuthorDataFetcher())
                        .dataFetcher("pageCount", graphQLDataFetchers.getPageCountDataFetcher()))
                .type(TypeRuntimeWiring.newTypeWiring("Mutation")
                        .dataFetcher("hello", graphQLDataFetchers.hello())
                        .dataFetcher("bad", graphQLDataFetchers.badFetcher()))
                .build();
    }
}