using Newtonsoft.Json;
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace AutoUnity
{
    public class ServiceConfigure:INotifyPropertyChanged
    {
        List<UnityRegisterParamCollection> unityRegisterParamCollections = new List<UnityRegisterParamCollection>();
        public string ErrMsg { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        public string OutPath { get; set; }
        public bool Load(string xlsxfile)
        {

            ErrMsg = "";
            int c_typeAssembly = 1;
            int c_typeNamespace = 2;
            int c_type = 3;
            int c_mapToAssembly = 4;
            int c_mapToNamespace = 5;
            int c_mapTo = 6;
            int c_name = 7;
            int c_serviceId = 8;
            int c_connName = 9;


            unityRegisterParamCollections.Clear();
            using (ExcelPackage packages = new ExcelPackage(new FileInfo(xlsxfile)))
            {
                foreach (var sheet in packages.Workbook.Worksheets)
                {
                    UnityRegisterParamCollection unityRegisterParamCollection = new UnityRegisterParamCollection();
                    unityRegisterParamCollection.name = sheet.Name;


                    int row = 3;
                    while (true)
                    {
                        UnityRegisterParam unityRegisterParam = new UnityRegisterParam();
                        try
                        {
                            string strAssembly = sheet.Cells[row, c_typeAssembly].Value.ToString();
                            string strNameSpace = sheet.Cells[row, c_typeNamespace].Value.ToString();
                            string strType = sheet.Cells[row, c_type].Value.ToString();

                            unityRegisterParam.type =
                                $"{strNameSpace}.{strType},{strAssembly}";

                        }
                        catch (Exception e)
                        {
                            //没有类型数据，结束了
                            break;
                        }

                        try
                        {
                            string strAssembly = sheet.Cells[row, c_mapToAssembly].Value.ToString();
                            string strNameSpace = sheet.Cells[row, c_mapToNamespace].Value.ToString();
                            string strMapTo = sheet.Cells[row, c_mapTo].Value.ToString();

                            unityRegisterParam.mapTo =
                                $"{strNameSpace}.{strMapTo},{strAssembly}";

                        }
                        catch (Exception e)
                        {
                            //可以没有mapTo
                        }

                        try
                        {
                            unityRegisterParam.name = sheet.Cells[row, c_name].Value.ToString();
                        }
                        catch (Exception e)
                        {
                            //可以没有name
                        }

                        try
                        {
                            unityRegisterParam.serviceId = sheet.Cells[row, c_serviceId].Value.ToString();
                        }
                        catch (Exception e)
                        {
                            //不能没有serviceId
                            ErrMsg = $"{unityRegisterParam.type} 不能没有serviceId";
                            return false;
                        }

                        try
                        {
                            unityRegisterParam.connName = sheet.Cells[row, c_connName].Value.ToString();
                        }
                        catch (Exception e)
                        {
                            //不能没有serviceId
                            ErrMsg = $"{unityRegisterParam.type} 不能没有connName";
                            return false;
                        }

                        unityRegisterParamCollection.unityRegisterParams.Add(unityRegisterParam);
                        row++;
                    }
                    unityRegisterParamCollections.Add(unityRegisterParamCollection);
                }
            }

            OutPath = Path.GetDirectoryName(xlsxfile);
            return true;
        }

        void ToXml(UnityRegisterParamCollection unityRegisterParamCollection) 
        {
            XDocument xdoc = new XDocument();
            //创建根元素
            XElement x_configuration = new XElement("configuration");
            //把根元素添加到文件中
            xdoc.Add(x_configuration);

            XElement x_configSections = new XElement("configSections");
            x_configuration.Add(x_configSections);

            XElement x_section = new XElement("section");
            x_configSections.Add(x_section);
            x_section.Add(
                new XAttribute("name", "unity"),
                new XAttribute("type", "Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration")
                );


            //XNamespace ns = "http://schemas.microsoft.com/practices/2010/unity";
            XElement x_unity = new XElement("unity");// (ns+"unity");
            x_configuration.Add(x_unity);


            XElement x_container = new XElement("container");
            x_unity.Add(x_container);

            foreach (var unityRegisterParam in unityRegisterParamCollection.unityRegisterParams) 
            {
                XElement x_register = new XElement("register");
                x_container.Add(x_register);

                x_register.SetAttributeValue("type", unityRegisterParam.type);

                if(!string.IsNullOrEmpty(unityRegisterParam.mapTo))
                    x_register.SetAttributeValue("mapTo", unityRegisterParam.mapTo);
                
                if (!string.IsNullOrEmpty(unityRegisterParam.name))
                    x_register.SetAttributeValue("name", unityRegisterParam.name);

                XElement x_lifetime = new XElement("lifetime");
                x_register.Add(x_lifetime);
                x_lifetime.Add(
                    new XAttribute("type", "singleton")
                    );
                

                XElement x_constructor = new XElement("constructor");
                x_register.Add(x_constructor);

                XElement x_param1 = new XElement("param");
                x_constructor.Add(x_param1);
                x_param1.Add(
                    new XAttribute("name", "serviceId"),
                    new XAttribute("value", unityRegisterParam.serviceId)
                    );

                XElement x_param2 = new XElement("param");
                x_constructor.Add(x_param2);
                x_param2.Add(
                    new XAttribute("name", "connName"),
                    new XAttribute("dependencyName", unityRegisterParam.connName)
                    );
            }
            
            



            
            //保存
            string filepath = Path.Combine(OutPath, $"{unityRegisterParamCollection.name}.config");
            xdoc.Save(filepath);
        }

        public void ToXml() 
        {
            foreach (var unityRegisterParamCollection in unityRegisterParamCollections)
            {
                ToXml(unityRegisterParamCollection);
            }
        }
    }

    public class UnityRegisterParamCollection 
    {
        public string name;
        public List<UnityRegisterParam> unityRegisterParams = new List<UnityRegisterParam>();
    }
}
