using UnityEngine;
using System.Xml;
using System.IO;
using System.Text;

using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System;

public class XmlProcess:IDisposable
{
    public string original_filepath;
    public string encode_filepath;
    public string decode_filepath;
    public string info;

    public XmlProcess() { }
    public XmlProcess(string filepath)
    {
        original_filepath = filepath;
        string path = Path.GetDirectoryName(filepath);
        string filename = Path.GetFileName(filepath);
        encode_filepath = path + "/en" + filename;
        decode_filepath = path + "/de" + filename;
    }

    public string GetIPAddress()
    {
        string filepath = Application.dataPath + @"/xml/LoginSetting.xml";

        if (File.Exists(filepath))
        {
            XmlDocument xmlDoc = new XmlDocument();
            //根据路径将XML读取出来   
            xmlDoc.Load(filepath);

            XmlNodeList nodeList = xmlDoc.SelectSingleNode("assets").ChildNodes;
            //遍历所有节点 
            foreach (XmlElement cus in nodeList)
            {
                if (cus.GetAttribute("id") == "1")
                {
                    //遍历所有子节点   
                    foreach (XmlElement xe in cus)
                    {
                        //拿到ip的节点   
                        if (xe.Name == "ip")
                            return xe.InnerText.Trim();
                    }
                }
            }
        }

        return string.Empty;
    }

    public string GetPort()
    {
        string filepath = Application.dataPath + @"/xml/LoginSetting.xml";

        if (File.Exists(filepath))
        {
            XmlDocument xmlDoc = new XmlDocument();
            //根据路径将XML读取出来   
            xmlDoc.Load(filepath);

            XmlNodeList nodeList = xmlDoc.SelectSingleNode("assets").ChildNodes;
            //遍历所有节点 
            foreach (XmlElement cus in nodeList)
            {
                if (cus.GetAttribute("id") == "1")
                {
                    //遍历所有子节点   
                    foreach (XmlElement xe in cus)
                    {
                        //拿到ip的节点   
                        if (xe.Name == "port")
                            return xe.InnerText.Trim();
                    }
                }
            }
        }

        return string.Empty;
    }

    public bool CheckUnique(string root, string info)
    {
        string uniqueID = SystemInfo.deviceUniqueIdentifier;//获取机器唯一识别码
        if (File.Exists(original_filepath))//证明这次是第一次运行该程序,获取当前配置文件
        {
            SetInfo(root, info, elem_value: uniqueID);
            GenerateEncodeXML1(root);
            return true;
        }
        else if (File.Exists(encode_filepath))
        {
            fileDcryption(encode_filepath);
            if (File.Exists(decode_filepath))
            {
                var id = GetInfo(decode_filepath, root, info);
                File.Delete(decode_filepath);
                if (id == uniqueID)
                    return true;//验证合格
                else
                    return false;
            }
        }
        //没有找到相关文件
        return false;
    }


    /// <summary>
    /// 唯一识别号匹配,匹配成功返回true
    /// </summary>
    /// <param name="root"></param>
    /// <param name="info"></param>
    /// <returns></returns>
    public void GetMode(string root,ref bool smart,ref bool unique,ref bool validity)
    {
        if (File.Exists(original_filepath))//证明这次是第一次运行该程序,获取当前配置文件
        {
            smart = bool.Parse(GetInfo(original_filepath, "assets", "SmartX1"));// 
            unique = bool.Parse(GetInfo(original_filepath, "assets", "Unique"));
            validity = bool.Parse(GetInfo(original_filepath, "assets", "Validity")); 
            GenerateEncodeXML1(root);
        }
        else if (File.Exists(encode_filepath))
        {
            fileDcryption(encode_filepath);
            if (File.Exists(decode_filepath))
            {
                smart = bool.Parse(GetInfo(decode_filepath, "assets", "SmartX1"));// 
                unique = bool.Parse(GetInfo(decode_filepath, "assets", "Unique"));
                validity = bool.Parse(GetInfo(decode_filepath, "assets", "Validity"));
                File.Delete(decode_filepath);
            }
        }
        else
        {
            smart = true;
        }
        //没有找到相关文件,全部不启用
        
    }
    public void SmartControlXML(ref string appid,string elem1= "SmartX1", string elem2= "BaseInfo", string elem3= "AppID")
    {
        if (File.Exists(original_filepath))//证明这次是第一次运行该程序,获取当前配置文件
        {
            appid = GetInfo(original_filepath, elem1, elem2, elem3);
            //StartCoroutine(GenerateEncodeXML());
            GenerateEncodeXML1(elem1);
        }
        else if (File.Exists(encode_filepath))
        {
            fileDcryption(encode_filepath);
            if (File.Exists(decode_filepath))
            {
                appid = GetInfo(decode_filepath, elem1, elem2, elem3);
                File.Delete(decode_filepath);
            }
        }
        else
        {
            //没有找到加密文件
            appid = null;
        }
    }

    public ValidityEntiy GetValidityEntiy(string rootstr )
    {
        if (File.Exists(original_filepath))//证明这次是第一次运行该程序,获取当前时间,写入配置文件
        {
            string validity = GetInfo(original_filepath, rootstr, "validity");
            ValidityEntiy vali = new ValidityEntiy(validity);
            string time = GetInfo(original_filepath, rootstr, "time");
            vali.time = time;
            if (string.IsNullOrEmpty(time))
            {
                SetInfo(original_filepath, rootstr, "time", elem_value: Convert.ToString(DateTime.Now));
            }
            GenerateEncodeXML1(rootstr);
            return vali;
        }
        else if (File.Exists(encode_filepath))
        {
            fileDcryption(encode_filepath);
            if (File.Exists(decode_filepath))
            {
                string validity = GetInfo(decode_filepath, rootstr, "validity");
                ValidityEntiy vali = new ValidityEntiy(validity);
                string time = GetInfo(decode_filepath, rootstr, "time");
                vali.time = time;
                File.Delete(decode_filepath);
                return vali;
            }
        }
        return ValidityEntiy.UnValidity();
    }

    /// <summary>
    /// 获取需要的信息
    /// </summary>
    /// <param name="filepath">文件路径</param>
    /// <param name="root">根节点名</param>
    /// <param name="info1">子节点名</param>
    /// <returns></returns>
    public string GetInfo(string filepath, string root, string info1 = null, string info2 = null, string info3 = null)
    {
        string value = "";
        if (File.Exists(filepath))
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filepath);
            XmlNode rootNdoe = xmlDoc.SelectSingleNode(root);
            XmlNodeList nodeList = rootNdoe.ChildNodes;
            foreach (XmlElement elem1 in nodeList)
            {
                if (elem1.Name == info1)
                {
                    if (string.IsNullOrEmpty(info2))
                    {
                        value = elem1.InnerText;
                        break;
                    }
                    else
                    {
                        foreach (XmlElement elem2 in elem1.ChildNodes)
                        {
                            if (elem2.Name == info2)
                            {
                                if (string.IsNullOrEmpty(info3))
                                {
                                    value = elem2.InnerText;
                                    break;
                                }
                                else
                                {
                                    foreach (XmlElement elem3 in elem2.ChildNodes)
                                    {
                                        if (elem3.Name == info3)
                                        {
                                            value = elem3.InnerText;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            }
        }
        return value;
    }

    public void SetInfo(string filepath,string rootstr, string elem1_ = null, string elem2_ = null, string elem3_ = null, string elem_value = null)
    {
        if (File.Exists(filepath))
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(original_filepath);
            XmlNode root = xmlDoc.SelectSingleNode(rootstr);
            XmlNodeList nodeList = root.ChildNodes;
            foreach (XmlElement elem1 in nodeList)
            {
                if (elem1.Name == elem1_)
                {
                    if (string.IsNullOrEmpty(elem2_))
                    {
                        elem1.InnerText = elem_value;
                        break;
                    }
                    else
                    {
                        foreach (XmlElement elem2 in elem1.ChildNodes)
                        {
                            if (elem2.Name == elem2_)
                            {
                                if (string.IsNullOrEmpty(elem3_))
                                {
                                    elem2.InnerText = elem_value;
                                    break;
                                }
                                else
                                {
                                    foreach (XmlElement elem3 in elem2.ChildNodes)
                                    {
                                        if (elem3.Name == elem3_)
                                        {
                                            elem3.InnerText = elem_value;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

            }
            xmlDoc.Save(filepath);
        }
    }

    /// <summary>
    /// 生成加密的xml文件
    /// </summary>
    public void GenerateEncodeXML1(string root)
    {
        fileEncryption(original_filepath,root);
        if (File.Exists(encode_filepath))
        {
            File.Delete(original_filepath);
        }
    }

    /// <summary>
    /// 加密xml文件
    /// </summary>
    /// <param name="doc"></param>
    /// <param name="ElementName"></param>
    /// <param name="key"></param>
    private void Encrypt(XmlDocument doc, string ElementName, SymmetricAlgorithm key)
    {
        XmlElement elementEncrypt = doc.GetElementsByTagName(ElementName)[0] as XmlElement;
        EncryptedXml eXml = new EncryptedXml();
        byte[] encryptElement = eXml.EncryptData(elementEncrypt, key, false);//
        EncryptedData edElement = new EncryptedData();
        edElement.Type = EncryptedXml.XmlEncElementUrl;
        string encryptionMethod = null;

        if (key is TripleDES)
        {
            encryptionMethod = EncryptedXml.XmlEncTripleDESUrl;
        }
        else if (key is DES)
        {
            encryptionMethod = EncryptedXml.XmlEncDESUrl;
        }

        if (key is Rijndael)
        {
            switch (key.KeySize)
            {
                case 128:
                    encryptionMethod = EncryptedXml.XmlEncAES128Url;
                    break;
                case 192:
                    encryptionMethod = EncryptedXml.XmlEncAES192Url;
                    break;
                case 256:
                    encryptionMethod = EncryptedXml.XmlEncAES256Url;
                    break;
            }
        }
        edElement.EncryptionMethod = new EncryptionMethod(encryptionMethod);
        edElement.CipherData.CipherValue = encryptElement;
        EncryptedXml.ReplaceElement(elementEncrypt, edElement, false);
    }

    /// <summary>
    /// XML文件解密
    /// </summary>
    /// <param name="doc"></param>
    /// <param name="Alg"></param>
    private void Decrypt(XmlDocument doc, SymmetricAlgorithm Alg)
    {
        XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
        EncryptedData edElement = new EncryptedData();
        edElement.LoadXml(encryptedElement);
        EncryptedXml exml = new EncryptedXml();
        byte[] rgbOutput = exml.DecryptData(edElement, Alg);
        exml.ReplaceData(encryptedElement, rgbOutput);
    }

    /// <summary>
    /// 举例,对某个XML文件加密
    /// </summary>
    /// <param name="filename"></param>
    private void fileEncryption(string filename,string root)
    {
        RijndaelManaged key = new RijndaelManaged();
        //设置密钥:key为32位=数字或字母16个=汉子8个
        byte[] byteKey = Encoding.Unicode.GetBytes("1111111111111111");
        key.Key = byteKey;
        XmlDocument xmldoc = new XmlDocument();
        xmldoc.PreserveWhitespace = true;
        xmldoc.Load(original_filepath);//想要加密的xml文件
        Encrypt(xmldoc, root, key);//需要加密的节点
        if (key != null)
        {
            key.Clear();
        }
        xmldoc.Save(encode_filepath);//生成加密后的xml文件
    }
    /// <summary>
    /// 举例,对某个xml文件解密
    /// </summary>
    /// <param name="filename"></param>
    private void fileDcryption(string filename)
    {
        RijndaelManaged key = new RijndaelManaged();
        byte[] byteKey = Encoding.Unicode.GetBytes("1111111111111111");
        key.Key = byteKey;
        XmlDocument xmldoc = new XmlDocument();
        xmldoc.PreserveWhitespace = true;
        xmldoc.Load(encode_filepath);//加载要解密的xml文件
        Decrypt(xmldoc, key);
        if (key != null)
        {
            key.Clear();
        }
        xmldoc.Save(decode_filepath);//生成解密后的文件
    }

    public void Dispose()
    {
        
    }
}