using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace NEIntelligentControl2.Models.Messages
{
    /// <summary>
    /// 用于进行WEB请求
    /// </summary>
    public class WEBHelper
    {
        /// <summary>
        /// 全局JSON配置
        /// </summary>
        private readonly JsonSerializerOptions _jso = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, IgnoreNullValues = true };
        /// <summary>
        /// 凭据
        /// </summary>
        public string Token { get; set; }

        public WEBHelper()
        {
            _jso.Converters.Add(new DateTiemConverter());
            _jso.Converters.Add(new DoubleConverter());
        }
        /// <summary>
        /// 使用POST请求数据，无返回值，用于更新与添加，数据以JSON形式附加在Body中
        /// </summary>
        /// <param name="url">请求链接</param>
        /// <param name="jval">附加的数据</param>
        public T HttpPostBody<T>(string url, object jval)
        {
            HttpWebRequest request = WebRequest.CreateHttp(url);
            request.Method = "POST";
            request.ContentType = "application/json";// ;charset=utf-8  application/x-www-form-urlencoded
            request.Headers.Add("Authorization",Token);
            if (jval != null)
            {
                var vl = JsonSerializer.Serialize(jval, _jso);
                var vs = Encoding.Default.GetBytes(vl);
                using (Stream st = request.GetRequestStream())
                {
                    st.Write(vs, 0, vs.Length);
                }
            }
            WebResponse res = request.GetResponse();
            T value = default;
            using (StreamReader reader = new StreamReader(res.GetResponseStream()))
            {
                var val = reader.ReadToEnd();
#if(DEBUG)
                Console.WriteLine(val);
#endif
                value = JsonSerializer.Deserialize<T>(val, _jso);
            }
            return value;
        }

        /// <summary>
        /// 异步使用POST请求数据，无返回值，用于更新与添加，数据以JSON形式附加在Body中
        /// </summary>
        /// <param name="url">请求链接</param>
        /// <param name="jval">附加的数据</param>
        public async Task<T> HttpPostBodyAsync<T>(string url, object jval)
        {
            return await Task.Run(() => HttpPostBody<T>(url, jval));
        }/// <summary>
         /// 使用POST请求数据，用于更新与添加，数据以JSON形式附加在Body中
         /// </summary>
         /// <param name="url">请求链接</param>
         /// <param name="jval">附加的数据</param>
        internal string HttpPostBodyString(string url, object jval)
        {
            HttpWebRequest request = WebRequest.CreateHttp(url);
            request.Method = "POST";
            request.ContentType = "application/json";// ;charset=utf-8  application/x-www-form-urlencoded
            request.Headers.Add("Authorization", Token);
            if (jval != null)
            {
                var vl = JsonSerializer.Serialize(jval, _jso);
                var vs = Encoding.Default.GetBytes(vl);
                using (Stream st = request.GetRequestStream())
                {
                    st.Write(vs, 0, vs.Length);
                }
            }
            WebResponse res = request.GetResponse();
            using (StreamReader reader = new StreamReader(res.GetResponseStream()))
            {
                var val = reader.ReadToEnd();
                return val;
            }
        }

        /// <summary>
        /// 使用GET请求数据（只能请求返回值为JSON格式的数据）
        /// </summary>
        /// <typeparam name="T">得到的数据</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="y">请求参数</param>
        /// <returns>请求类型</returns>
        public T HttpGetJSON<T>(string url)
        {
            HttpWebRequest request = WebRequest.CreateHttp(url);
            request.Headers.Add("Authorization", Token);
            WebResponse res = request.GetResponse();
            string val = "";
            using (StreamReader reader = new StreamReader(res.GetResponseStream()))
            {
                val = reader.ReadToEnd();
            }
            request.Abort();
            var tt = JsonSerializer.Deserialize<T>(val, _jso);
            return tt;
        }


        /// <summary>
        /// 使用GET请求数据，获得请求字符串
        /// </summary>
        /// <typeparam name="T">得到的数据</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="y">请求参数</param>
        /// <returns>请求类型</returns>
        public string HttpGetString(string url)
        {
            HttpWebRequest request = WebRequest.CreateHttp(url);
            request.Headers.Add("Authorization", Token);
            WebResponse res = request.GetResponse();
            string val = "";
            using (StreamReader reader = new StreamReader(res.GetResponseStream()))
            {
                val = reader.ReadToEnd();
            }
            request.Abort();
            return val;
        }

        /// <summary>
        /// 使用GET请求数据，异步方法（只能请求返回值为JSON格式的数据）
        /// </summary>
        /// <typeparam name="T">得到的数据</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="y">请求参数</param>
        /// <returns>请求类型</returns>
        public async Task<T> HttpGetJSONAsync<T>(string url)
        {
            return await Task.Run(() =>
            {
                return HttpGetJSON<T>(url);
            });
        }


        /// <summary>
        /// 使用GET请求数据（只能请求返回值为JSON格式的数据）
        /// </summary>
        /// <typeparam name="T">得到的数据</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="y">请求参数</param>
        /// <returns>请求类型</returns>
        public string HttpGetString(string url, object args)
        {
            string arg = GetArgs(args);
            var ur = url + arg;
            HttpWebRequest request = WebRequest.CreateHttp(ur);
            WebResponse res = request.GetResponse();
            string val = "";
            using (StreamReader reader = new StreamReader(res.GetResponseStream()))
            {
                val = reader.ReadToEnd();
            }
            request.Abort();
            return val;
        }


        /// <summary>
        /// 将对象转换成请求字符串
        /// </summary>
        /// <param name="args">要转换的对象</param>
        /// <returns>转换后的字符串</returns>
        private string GetArgs(object args)
        {
            if (args == null) return "";
            StringBuilder sb = new StringBuilder();
            sb.Append("?");
            var tp = args.GetType();
            var pr = tp.GetProperties();
            bool isFirst = true;
            foreach (var v in pr)
            {
                var vv = v.GetValue(args)?.ToString();
                if (string.IsNullOrWhiteSpace(vv)) continue;
                if (!isFirst)
                {
                    sb.Append("&");
                }
                sb.Append(v.Name).Append("=").Append(vv);
                isFirst = false;
            }
            return sb.ToString();
        }

        /// <summary>
        /// JSON编码
        /// </summary>
        public string Serialize(object obj)
        {
            return JsonSerializer.Serialize(obj, _jso);
        }


        /// <summary>
        /// JSON解码
        /// </summary>
        public T Deserialize<T>(string s)
        {
            return JsonSerializer.Deserialize<T>(s, _jso);
        }
    }

    /// <summary>
    /// JSON时间转换
    /// </summary>
    public class DateTiemConverter : JsonConverter<DateTime>
    {
        public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            DateTime.TryParse(reader.GetString(), out DateTime dt);
            return dt;
        }

        public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
        }
    }

    /// <summary>
    /// JSON时间转换
    /// </summary>
    public class DoubleConverter : JsonConverter<double>
    {
        public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if(reader.TokenType== JsonTokenType.Number)
            {
                reader.TryGetDouble(out double d);
                return d;
            }
            double.TryParse(reader.GetString(), out double d2);
            return d2;
        }

        public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
        {
            writer.WriteStringValue(value.ToString());
        }
    }
}
