
using Furion;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;

namespace Ewide.Core.Util
{
    public class XmlSerializerUtil
    {
        /// <summary>
        /// XML 要读取的路径
        /// </summary>
        private string DirPath { set; get; }
        /// <summary>
        /// 当前程序集
        /// </summary>
        private string currentAssemblyName { get { return "Ewide.Core"; } }
        /// <summary>
        /// 读取文件夹下所有XML  
        /// add-migration init -c defaultDbContext 备用数据
        /// </summary>
        /// <returns></returns>
        public Dictionary<Type, object> ReaderALL()
        {
            string dirPath = CurrentDirPath();
            Dictionary<Type, object> dic = new Dictionary<Type, object>();
            DirectoryInfo folder = new DirectoryInfo(dirPath);
            foreach (FileInfo file in folder.GetFiles())
            {
                //除去.xml 后缀
                string className = file.Name.Remove(file.Name.Length - 4, 4);
                object obj = AppInfo(className);
                string XmlContext = StreamRead(file.FullName);
                //实例创建 出 类型集合 
                var modelList = Activator.CreateInstance(typeof(List<>).MakeGenericType(new Type[] { obj.GetType() }));
                var list = Deserialize(modelList.GetType(), XmlContext);
                dic.Add(obj.GetType(), list);
            }
            return dic;
        }
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="type"></param>
        /// <param name="xmlContent">XML内容</param>
        /// <returns></returns>
        private object Deserialize(Type type, string xmlContent)
        {
            object obj = null;
            using (StringReader sr = new StringReader(xmlContent))
            {
                XmlSerializer xmldes = new XmlSerializer(type);
                obj = xmldes.Deserialize(sr);
            }
            return obj;
        }
        /// <summary>
        /// 数据流读取
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string StreamRead(string path)
        {
            using (StreamReader reader = new StreamReader(path, Encoding.Default))
            {
                return reader.ReadToEnd();
            }
        }
        /// <summary>
        /// 反射 根据类名 反射整个类 得到实例
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private object AppInfo(string name)
        {
            if (name == "BsHouseProjectInfo")  //BsHouseProjectInfo 这个类 写在 application 程序集
            {
                string fullNamei = string.Join('.', "Ewide.Application.Entity", name);
                return Assembly.Load("Ewide.Application").CreateInstance(fullNamei);
            }
            string fullName = string.Join('.', currentAssemblyName, name);
            return Assembly.Load(currentAssemblyName).CreateInstance(fullName);
        }
        /// <summary>
        /// 写入XML到磁盘
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="data">数据</param>
        /// <param name="className">XML名称</param>
        public void WriteXML(Type type, object data, string className)
        {
            string writePath = CurrentDirPath(className);
            using (FileStream fs = new FileStream(writePath, FileMode.OpenOrCreate))
            {
                XmlSerializer ser = new XmlSerializer(type);
                ser.Serialize(fs, data);
            }
        }
        /// <summary>
        /// 要操作的文件夹目录 
        /// </summary>
        /// <returns></returns>
        private string CurrentDirPath()
        {
            // 在for 循环里， 不用每次都读取 下面的代码
            if (DirPath != null)
                return DirPath;

            string targetPath = String.Empty;
            string appConfigPath = App.Configuration["WriteXmlPath:ReadSelect"] == "SeedData" ? App.Configuration["WriteXmlPath:SeedData"] : App.Configuration["WriteXmlPath:DataBase"];
            string path = Directory.GetCurrentDirectory();
            DirectoryInfo dirInfo = new DirectoryInfo(path);
            foreach (DirectoryInfo item in dirInfo.Parent.GetDirectories())
            {
                if (item.Name == currentAssemblyName)
                {
                    var queryList = item.GetDirectories().Where(s => s.Name == appConfigPath);
                    if (!queryList.Any()) item.CreateSubdirectory(appConfigPath);
                    targetPath = item.GetDirectories(appConfigPath).FirstOrDefault().FullName;
                    break;
                }
            }
            DirPath = targetPath;
            return targetPath;
        }
        /// <summary>
        /// 根据类名 创建一个XML文件 写入数据
        /// </summary>
        /// <param name="className"></param>
        /// <returns></returns>
        private string CurrentDirPath(string className)
        {
            string path = CurrentDirPath();
            return string.Join(@"\", path, className + ".xml");
        }
        /// <summary>
        /// 写入种子数据  --不常用
        /// </summary>
        public void WriteDataSeed()
        {
            Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.GetName().Name.Contains("Ewide.Core"));
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                //if (type.Name.EndsWith("SeedData"))
                if (type.Name.EndsWith("SysEmpExtOrgPos"))
                {
                    object obHelper = Activator.CreateInstance(type);
                    MethodInfo methodinfo = type.GetMethod("HasData");
                    object objs = methodinfo.Invoke(obHelper, new object[] { null, null });
                    Type objType = objs.GetType();
                    //if (objType.Name == "SysEmpExtOrgPos[]" || objType.Name == "SysConfig[]" || objType.Name == "SysDictData[]" || objType.Name == "SysDictType[]" || objType.Name == "SysEmpPos[]" || objType.Name == "SysEmp[]" || objType.Name == "SysMenu[]" || objType.Name == "SysOrg[]" || objType.Name == "SysPos[]" || objType.Name == "SysRole[]" || objType.Name == "SysTenant[]" || objType.Name == "SysTimer[]" || objType.Name == "SysUser[]")
                    if (objType.Name == "SysEmpExtOrgPos[]")
                    {
                        string className = objType.Name.Remove(objType.Name.Length - 2, 2);
                        WriteXML(objType, objs, className);
                    }
                }
            }
        }
    }
}
