using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

namespace RothenburgAR.Updater
{
    public class HttpRequest
    {
        private readonly string url;
        private readonly HttpVerb verb;
        private string uploadData;

        private Dictionary<string, string> headerEntries = new Dictionary<string, string>();

        public HttpRequest(String url, HttpVerb verb, String uploadData = null)
        {
            this.url = url;
            this.verb = verb;
            this.uploadData = uploadData;
        }

        public HttpRequest WithHeader(string header, string value)
        {
            headerEntries.Add(header, value);
            return this;
        }

        public HttpHandler Send()
        {
            Debug.Log(string.Format("{1}-Downloading {0}", url, Time.realtimeSinceStartup));
            DownloadHandler dl = new DownloadHandlerBuffer();
            UploadHandlerRaw ul = null;
            if (uploadData != null && uploadData != string.Empty)
            {
                ul = new UploadHandlerRaw(Encoding.UTF8.GetBytes(uploadData.ToCharArray()));
            }

            string verb = Enum.GetName(typeof(HttpVerb), this.verb);

            UnityWebRequest wr = new UnityWebRequest(url, verb, dl, ul);
            wr.SetRequestHeader("Content-Type", "application/json;charset=UTF-8");
            foreach (var entry in headerEntries) { wr.SetRequestHeader(entry.Key, entry.Value); }

            var operation = wr.SendWebRequest();

            return new HttpHandler(ul, dl, wr, operation);
        }
    }

    public enum HttpVerb
    {
        GET,
        POST,
        PUT,
        DELETE
    }

    public class HttpHandler
    {
        public UploadHandler Upload { get; set; }
        public DownloadHandler Download { get; set; }
        public UnityWebRequest Request { get; set; }
        public UnityWebRequestAsyncOperation Operation { get; set; }

        private bool isDone = false;
        public bool IsError { get; set; }

        public bool IsDone
        {
            get
            {
                return Operation.isDone && Request.isDone && this.isDone;
            }
        }

        public HttpHandler(UploadHandler upload, DownloadHandler download, UnityWebRequest request, UnityWebRequestAsyncOperation operation)
        {
            this.Upload = upload;
            this.Download = download;
            this.Request = request;
            this.Operation = operation;

            this.Operation.completed += (_) =>
            {
                this.isDone = true;
                this.IsError =
                    request.isNetworkError
                    || request.isHttpError
                    // Error when answer is empty except when it's a 300 error code
                    || (!(request.responseCode >= 300 && request.responseCode < 400) && download.data.Length == 0);
            };
        }
    }


}
