using System.Xml;
using System.Xml.Serialization;
using NewRock.Sdk.Security;

namespace NewRock.Sdk.Extensions
{
    public static class XmlSerializeExtensions
    {
        private static readonly string _authMarkupBegin = "<Auth>";
        private static readonly string _authMarkupClose = "</Auth>";
        private static readonly string _unAuthMarkup = "<unauthorized/>";
        private static readonly string _failedMarkup = "<Event attribute=\"FAILED\">";

        //public static string Serialize<T>(this T value)
        //{
        //    if (value == null)
        //        throw new ArgumentNullException("序列化参数为空值");

        //    var serializer = new XmlSerializer(typeof(T));
        //    using var sw = new StringWriter();
        //    serializer.Serialize(sw, value);
        //    return sw.ToString();
        //}

        public static T? Deserialize<T>(this Stream stream) where T : class
        {
            //var sr = new StreamReader(stream);
            //var content = await sr.ReadToEndAsync();
            //return Deserialize<T>(content);
            var serializer = new XmlSerializer(typeof(T));
            var rsp = serializer.Deserialize(stream) as T;
            return rsp;
        }

        public static T? Deserialize<T>(this string content) where T : class
        {
            if (string.IsNullOrEmpty(content))
                return null;

            var serializer = new XmlSerializer(typeof(T));
            using var sr = new StringReader(content);
            return serializer.Deserialize(sr) as T;

            //var bytes = Encoding.Unicode.GetBytes(content);
            //var stream = new MemoryStream(bytes);
            //return stream.Deserialize<T>();
        }

        public static T? DeserializeWithErrorMsg<T>(this string content) where T : NewRockResponse
        {
            if (content.Contains(_failedMarkup))
            {
                var err = content.Deserialize<NewRockErrorResponse>();
                var resp = Activator.CreateInstance<T>();
                resp.Error = err;
                return resp;
            }

            return Deserialize<T>(content);
        }

        public static (T? value, NewRockAuthorize? authorize) DeserializeWithAuthorize<T>(this string content) where T : class
        {
            if (string.IsNullOrEmpty(content))
                return new();

            string authStr;
            if (!content.Contains(_authMarkupBegin))
                return (Deserialize<T>(content), null);

            content = content.TrimEnd();
            if (content.EndsWith(_authMarkupClose))
            {
                var array = content.Split(_authMarkupBegin, StringSplitOptions.RemoveEmptyEntries);
                content = array.First();
                authStr = _authMarkupBegin + array.Last();
            }
            else
            {
                var array = content.Split(_authMarkupClose, StringSplitOptions.RemoveEmptyEntries);
                content = array.Last();
                authStr = array.First() + _authMarkupClose;
            }

            return (Deserialize<T>(content), Deserialize<NewRockAuthorize>(authStr));
        }

        /// <summary>
        /// xml序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="withHeader">带xml标准头</param>
        /// <param name="withNameSpace">带namespace</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static string Serialize<T>(this T value, bool withHeader = true, bool withNameSpace = false)
        {
            if (value == null)
                throw new ArgumentNullException("序列化参数为空值");

            var serializer = new XmlSerializer(typeof(T));

            using var sw = new StringWriter();
            var xmlWriteSettings = new XmlWriterSettings();
            //xmlWriteSettings.Encoding = Encoding.UTF8;
            xmlWriteSettings.OmitXmlDeclaration = !withHeader;

            using var xmlWriter = XmlWriter.Create(sw, xmlWriteSettings);
            if (withNameSpace)
            {
                serializer.Serialize(xmlWriter, value);
            }
            else
            {
                var nameSpace = new XmlSerializerNamespaces();
                nameSpace.Add(string.Empty, string.Empty);
                serializer.Serialize(xmlWriter, value, nameSpace);
            }
            Console.WriteLine(sw.ToString());
            return sw.ToString();
        }

        /// <summary>
        /// 带验证信息的xml序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="authorize">验证信息</param>
        /// <returns></returns>
        public static string Serialize<T>(this T value, NewRockAuthorize authorize)
            => $"{authorize.Serialize()}{value.Serialize(false)}";

        /// <summary>
        /// 验证授权
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static UnauthorizedResponse? Authentication(this string content)
        {
            if (string.IsNullOrEmpty(content))
                throw new ArgumentNullException(nameof(content));
            content = content.Replace(',', new());
            if (content.Contains(_unAuthMarkup))
            {
                var authString = content.Split(_unAuthMarkup, StringSplitOptions.RemoveEmptyEntries).Last();
                //Console.WriteLine(authString);
                return Deserialize<UnauthorizedResponse>(authString);
            }

            return null;
        }
    }
}
