using Assets.Scripts;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace Assets.Scripts.Apis
{
    public abstract class ApiBase
    {
        private static CookieContainer _cookieCollection = new CookieContainer();
        public static CookieCollection cookies
        {
            get
            {
                return _cookieCollection.GetCookies(new Uri(ConfigHelper.Host));
            }
            //set
            //{
            //    _cookieCollection = value;
            //}
        }
        //protected static EasyHttp.Http.HttpClient http;
        private static System.Net.Http.HttpClient httpClient;
        private static HttpClientHandler httpClientHandler;
        static ApiBase()
        {
            //http = new EasyHttp.Http.HttpClient();
            //http.Request.PersistCookies = true;

            httpClientHandler = new HttpClientHandler();
            httpClientHandler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

            httpClientHandler.CookieContainer = _cookieCollection;
            httpClientHandler.UseCookies = true;
            httpClientHandler.CookieContainer.Add(new Uri(ConfigHelper.Host), new Cookie("PowerFun.AUTH", "E1F130A03C0C2F01DF465A17AAA4740E9C44FC5F7C5077AF5A09B5ED29F0CF4FABE44329111C0BDBC6D97A28E7C7C188250265B37D2E6A849D7F0CAC606490648F17DC7FB9C8778BE7217991EBB6304BD543CFEE55084E54CCD634B49F26A751","/"));

            httpClient = new System.Net.Http.HttpClient(httpClientHandler);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("Unity", ConfigHelper.AppVersion));
        }

        protected async Task<bool> GetAsFileSync(string url, string fileName)
        {
            //var result = await Task.Factory.StartNew(() =>
            //{
            //    var res = http.GetAsFile(ConfigHelper.Host + url, fileName);
            //    return res;
            //});
            //return result;


            //using (var httpResponseMessage = await httpClient.SendAsync(CreateRequest(url, System.Net.Http.HttpMethod.Get), HttpCompletionOption.ResponseContentRead))
            //{
            byte[] data1 = await GetAsync(url);

            if (data1 != null)
            {
                using (var stream = new FileStream(fileName, FileMode.Create))
                {
                    stream.Write(data1, 0, data1.Length);
                }
                return true;
            }
            return false;
            //    return httpResponseMessage.IsSuccessStatusCode;
            //}
        }



        protected async Task<byte[]> GetAsync(string url)
        {
            AddLanguage();
            var httpResponseMessage = await httpClient.GetAsync(ConfigHelper.Host + url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            if (!httpResponseMessage.IsSuccessStatusCode)
            {
                return null;
            }
            byte[] data1 = await httpResponseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
            return data1;
        }

        protected async Task<byte[]> GetUrlAsync(string url)
        {
            var httpResponseMessage = await httpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            if (!httpResponseMessage.IsSuccessStatusCode)
            {
                return null;
            }
            byte[] data1 = await httpResponseMessage.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
            return data1;
        }
        //private HttpResponse Get(string url, object query = null)
        //{
        //    return http.Get(ConfigHelper.Host + url, query);
        //}

        protected async Task<T> GetAsync<T>(string url)
        {
            //var result = await Task.Factory.StartNew(() =>
            //{
            //    return Get(url, query);
            //});

            //return result;
            AddLanguage();
            var response = await httpClient.GetAsync(ConfigHelper.Host + url, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            return await ParseJsonAsync<T>(response);
        }

        private async Task<T> ParseJsonAsync<T>(HttpResponseMessage response)
        {
            var result = await response.Content.ReadAsStringAsync();
            Console.WriteLine(result);
            return JsonConvert.DeserializeObject<T>(result);
        }

        //protected T Post<T>(string url, object data)
        //{
        //    //var stream = new StreamContent()
        //    var stringContent = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
        //    AddLanguage();
        //    var response = httpClient.PostAsync(ConfigHelper.Host + url, stringContent).GetAwaiter()
        //        .GetResult();
        //    if (response.IsSuccessStatusCode == false)
        //    {
        //        //return default(T);

        //        throw new Exception($"服务器端返回：{ response.StatusCode }\r\n{ response.RequestMessage }");
        //    }
        //    var info = ParseJsonAsync<T>(response).GetAwaiter().GetResult();
        //    return info;
        //}

        //protected HttpResponse Post(string url, object data, IList<FileInfo> files)
        //{
        //    var formData = data.ToDictionary();
        //    IList<FileData> files1 = new List<FileData>();
        //    foreach (var item in files)
        //    {
        //        var fileData = new FileData();
        //        fileData.FieldName = item.Name;
        //        fileData.Filename = item.FullName;

        //        files1.Add(fileData);
        //    }
        //    return http.Post(ConfigHelper.Host + url, formData, files1);
        //}

        //protected async Task<HttpResponse> PostAsync(string url, object data, IList<FileInfo> files)
        //{
        //    var result = await Task.Factory.StartNew(() =>
        //    {
        //        return Post(url, data, files);
        //    });
        //    return result;
        //}

        protected string Upload(string url, object data, IList<string> files)
        {
            var files1 = new Dictionary<string, Stream>();
            foreach (var file in files)
            {
                //writer.Write( // file header
                //    $"\r\n--{boundary}\r\nContent-Disposition: " +
                //    $"form-data; name=\"{ Path.GetFileName(file) }\"; filename=\"{Path.GetFileName(file)}\"\r\n" +
                //    "Content-Type: application/octet-stream\r\n\r\n");

                //writer.Flush();
                var fileStream = File.OpenRead(file);
                //fileStream.CopyTo(requestStream);

                files1.Add(Path.GetFileName(file), fileStream);
            }

            return Upload(url, data, files1);
        }

        /// <summary>
        /// formdata
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <param name="files"></param>
        /// <returns></returns>
        protected string Upload(string url, object data, Dictionary<string, Stream> files)
        {
            //var requestContent = new MultipartFormDataContent();
            //foreach (var item in files)
            //{
            //    //    here you can specify boundary if you need---^
            //    //var file = new System.IO.FileInfo(item);
            //    var bytes = System.IO.File.ReadAllBytes(item);
            //    var imageContent = new ByteArrayContent(bytes);
            //    imageContent.Headers.ContentType =
            //        MediaTypeHeaderValue.Parse(GetMimeType(System.IO.Path.GetExtension(item)));

            //    requestContent.Add(imageContent, Path.GetFileName(item), Path.GetFileName(item));
            //}

            //var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonConvert.SerializeObject(data));
            //foreach (var item in dict)
            //{
            //    if (item.Value == null) continue;
            //    requestContent.Add(new StringContent(item.Value.ToString()), item.Key);
            //}

            //using (var res = await httpClient.PostAsync(ConfigHelper.Host + url, requestContent).ConfigureAwait(false))
            //{
            //    var rrr = await res.Content.ReadAsStringAsync().ConfigureAwait(false);

            //    return rrr;
            //}
            var request = (HttpWebRequest)WebRequest.Create(ConfigHelper.Host + url);
            request.UserAgent = httpClient.DefaultRequestHeaders.UserAgent.ToString();
            request.Headers.Add("Language", "Zh-cn");
            request.CookieContainer = new CookieContainer();
            foreach (Cookie item in cookies)
            {
                request.CookieContainer.Add(item);
            }

            var postData = new StringBuilder();
            var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(JsonConvert.SerializeObject(data));
            foreach (var item in values)
            {
                postData.Append(WebUtility.UrlEncode($"{ item.Key }={ item.Value }&"));
            }

            var boundary = $"{Guid.NewGuid():N}";
            request.ContentType = $"multipart/form-data; {nameof(boundary)}={boundary}";
            request.Method = "POST";
            request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;


            //byte[] bytes;
            //using (var stream = new MemoryStream())
            //using (var writer = new StreamWriter(stream))
            //{
            //    foreach (var ddd in values)
            //    {
            //        writer.Write( // put all POST data into request
            //            $"\r\n--{boundary}\r\nContent-Disposition: " +
            //            $"form-data; name=\"{ ddd.Key }\"\r\n\r\n{ ddd.Value }");
            //    }
            //    foreach (var file in files)
            //    {
            //        writer.Write( // file header
            //            $"\r\n--{boundary}\r\nContent-Disposition: " +
            //            $"form-data; name=\"{ Path.GetFileName(file) }\"; filename=\"{Path.GetFileName(file)}\"\r\n" +
            //            "Content-Type: application/octet-stream\r\n\r\n");

            //        writer.Flush();
            //        using (var fileStream = File.OpenRead(file))
            //            fileStream.CopyTo(stream);
            //    }
            //    writer.Write($"\r\n--{boundary}--\r\n");

            //    bytes = stream.ToArray();
            //}
            //using (Stream postStream = request.GetRequestStream())
            //{
            //    using (var zipStream = new GZipStream(postStream, CompressionMode.Compress))
            //    {
            //        zipStream.Write(bytes, 0, bytes.Length);
            //    }
            //}

            using (var requestStream = request.GetRequestStream())
            using (var writer = new StreamWriter(requestStream))
            {
                foreach (var ddd in values)
                {
                    writer.Write( // put all POST data into request
                        $"\r\n--{boundary}\r\nContent-Disposition: " +
                        $"form-data; name=\"{ ddd.Key }\"\r\n\r\n{ ddd.Value }");
                }
                foreach (var file in files)
                {
                    //writer.Write( // file header
                    //    $"\r\n--{boundary}\r\nContent-Disposition: " +
                    //    $"form-data; name=\"{ Path.GetFileName(file) }\"; filename=\"{Path.GetFileName(file)}\"\r\n" +
                    //    "Content-Type: application/octet-stream\r\n\r\n");

                    //writer.Flush();
                    //using (var fileStream = File.OpenRead(file))
                    //    fileStream.CopyTo(requestStream);


                    writer.Write( // file header
                        $"\r\n--{boundary}\r\nContent-Disposition: " +
                        $"form-data; name=\"{ file.Key }\"; filename=\"{ file.Key }\"\r\n" +
                        "Content-Type: application/octet-stream\r\n\r\n");

                    writer.Flush();
                    //using (var fileStream = File.OpenRead(file))
                    file.Value.CopyTo(requestStream);
                }
                writer.Write($"\r\n--{boundary}--\r\n");
            }

            using (var response = (HttpWebResponse)request.GetResponse())
            using (var responseStream = response.GetResponseStream())
            {
                if (responseStream == null)
                    return string.Empty;
                using (var reader = new StreamReader(responseStream))
                    return reader.ReadToEnd();
            }
        }

        private string GetMimeType(string extension)
        {
            if (extension.Contains(".txt"))
            {
                return "text/plain";
            }
            if (extension.Contains(".png"))
            {
                return "image/png";
            }
            return "application/octet-stream";
        }

        //protected async Task<string> PostUrlAsync(string url, string data)
        //{
        //    StringContent stringContent;
        //    if (data != null)
        //    {
        //        stringContent = new StringContent(data, Encoding.UTF8, "application/json");
        //    }
        //    else
        //    {
        //        stringContent = new StringContent("", Encoding.UTF8);
        //    }
        //    var response = await httpClient.PostAsync(url, stringContent).ConfigureAwait(false);
        //    var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        //    return result;
        //}

        protected async Task<string> PostAsync(string url, object data)
        {
            StringContent stringContent;
            if (data != null)
            {
                stringContent = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
            }
            else
            {
                stringContent = new StringContent("", Encoding.UTF8);
            }
            AddLanguage();
            var response = await httpClient.PostAsync(ConfigHelper.Host + url, stringContent).ConfigureAwait(false);
            var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            return result;
        }

        protected async Task<T> PostAsync<T>(string url, object data)
        {
            //var result = await Task.Factory.StartNew(() =>
            //{
            //    return Post(url, data);
            //});
            //new EasyHttp.Http.HttpResponse().Cookies
            //return result;


            StringContent stringContent;
            if (data != null)
            {
                var str = JsonConvert.SerializeObject(data);
                stringContent = new StringContent(str, Encoding.UTF8, "application/json");
            }
            else
            {
                stringContent = new StringContent("", Encoding.UTF8);
            }
            AddLanguage();
            var response = await httpClient.PostAsync(ConfigHelper.Host + url, stringContent).ConfigureAwait(false);
            //var cookies = response.Headers.GetValues("Set-Cookie");
            //if (cookies.Any())
            //{
            //    foreach (var cookie in cookies)
            //    {
            //        ApiBase.cookies.Add(cookie)
            //    }

            //}
            var info = await ParseJsonAsync<T>(response);
            return info;
        }

        //private static HttpRequestMessage CreateRequest(string url, System.Net.Http.HttpMethod method)
        //{
        //    HttpRequestMessage httpRequestMessage1 = new HttpRequestMessage();
        //    httpRequestMessage1.Method = method;
        //    Uri uri = new Uri(ConfigHelper.Host + url);
        //    httpRequestMessage1.RequestUri = uri;
        //    HttpRequestMessage httpRequestMessage2 = httpRequestMessage1;
        //    //if (requiresAuthentication)
        //    //    httpRequestMessage2.Headers.Authorization = this._authorization;
        //    return httpRequestMessage2;
        //}

        private void AddLanguage()
        {
            httpClient.DefaultRequestHeaders.Remove("Language");
            //httpClient.DefaultRequestHeaders.Add("Language", PubCommData.Lauguage);
        }

        /// <summary>
        /// 因为cef调用c#代码，异步请求在win7上会有问题，所以写了同步的方法
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public string Get(string url)
        {
            var url1 = url;
            if (url1.IndexOf("http") == -1)
            {
                url1 = ConfigHelper.Host + url1;
            }
            //AddLanguage();
            var request = (HttpWebRequest)WebRequest.Create(url1);
            request.Method = "GET";
            //foreach (var item in httpClient.DefaultRequestHeaders)
            //{
            //    request.Headers.Add(item.Key, item.Value.First());
            //}
            request.UserAgent = httpClient.DefaultRequestHeaders.UserAgent.ToString();
            request.Accept = "application/json";
            request.Headers.Add("Language", "Zh-cn");
            request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            request.CookieContainer = new CookieContainer();
            foreach (Cookie item in cookies)
            {
                request.CookieContainer.Add(item);
            }

            var res = request.GetResponse();
            using (var stream = new StreamReader(res.GetResponseStream()))
            {
                return stream.ReadToEnd();
            }
        }

        public T Get<T>(string url)
        {
            var res = Get(url);

            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(res);
        }

        /// <summary>
        /// 因为cef调用c#代码，异步请求在win7上会有问题，所以写了同步的方法
        /// </summary>
        /// <param name="url"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public string Post(string url, object data)
        {
            var request = (HttpWebRequest)WebRequest.Create(ConfigHelper.Host + url);
            request.Method = "POST";
            request.UserAgent = httpClient.DefaultRequestHeaders.UserAgent.ToString();
            request.Accept = "application/json";
            request.Headers.Add("Language", "Zh-cn");
            request.CookieContainer = new CookieContainer();
            foreach (Cookie item in cookies)
            {
                request.CookieContainer.Add(item);
            }

            request.ContentType = "application/json";
            if (data != null)
            {
                using (var streamWriter = new StreamWriter(request.GetRequestStream()))
                {
                    streamWriter.Write(Newtonsoft.Json.JsonConvert.SerializeObject(data));
                }
            }
            else
            {
                request.ContentLength = 0;
            }
            var res = request.GetResponse();
            using (var stream = new StreamReader(res.GetResponseStream()))
            {
                return stream.ReadToEnd();
            }
        }

        public T Post<T>(string url, object data)
        {
            return JsonConvert.DeserializeObject<T>(Post(url, data));
        }

        protected byte[] GetBytes(string url)
        {
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            using (Stream netStream = response.GetResponseStream())
            {
                var data = ((MemoryStream)netStream).ToArray();
                return data;
            }
        }
    }

}