using System;
using System.IO;
using System.Threading.Tasks;
using GraphQL;
using GraphQL.Http;
using GraphQL.Types;
using Microsoft.AspNetCore.Http;

namespace MySystem.PublicClass.GraphQL
{
    public class GraphQLMiddleware : BaseClass
    {
        private readonly RequestDelegate _next;
        private readonly IRepository _repository;

        public GraphQLMiddleware(RequestDelegate next, IRepository repository)
        {
            _next = next;
            _repository = repository;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            if (httpContext.Request.Path.StartsWithSegments("/g/api"))
            {
                //string token = httpContext.Request.Headers["token"].ToString();
                //string device = httpContext.Request.Headers["device"].ToString();
                //bool checkResult = CheckToken(httpContext, device, token);
                //if (checkResult)
                //{
                    if (httpContext.Request.Method == "GET")
                    {
                        var query = httpContext.Request.Query["query"];
                        if (!string.IsNullOrWhiteSpace(query))
                        {
                            Schema schema = new Schema { Query = new Query(_repository) };
                            var result = await new DocumentExecuter().ExecuteAsync(options =>
                            {
                                options.Schema = schema;
                                options.Query = query;
                            });
                            schema.Dispose();
                            await WriteResultAsync(httpContext, result);
                        }
                        else
                        {
                            await _next(httpContext);
                        }
                    }
                    else
                    {
                        var stream = new StreamReader(httpContext.Request.Body);
                        var query = await stream.ReadToEndAsync();
                        if (!string.IsNullOrWhiteSpace(query))
                        {
                            Schema schema = new Schema { Query = new Query(_repository) };
                            var result = await new DocumentExecuter().ExecuteAsync(options =>
                            {
                                options.Schema = schema;
                                options.Query = query;
                            });
                            schema.Dispose();
                            stream.Dispose();
                            await WriteResultAsync(httpContext, result);
                        }
                        else
                        {
                            stream.Dispose();
                            await _next(httpContext);
                        }
                    }
                //}
                //else
                //{
                //    await _next(httpContext);
                //}
            }
            else
            {
                await _next(httpContext);
            }
        }

        private async Task WriteResultAsync(HttpContext httpContext, ExecutionResult executionResult)
        {
            var json = new DocumentWriter(indent:true).Write(executionResult);
            httpContext.Response.StatusCode = 200;
            httpContext.Response.ContentType = "application/json";
            await httpContext.Response.WriteAsync(json);
        }
    }
}
