using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using Newtonsoft.Json.Linq;
using SXLibrary;
using Newtonsoft.Json;

namespace MOKA_Factory_Tools
{
    public class Keyinfo
    {
        public byte keyType { get; set; } = 0x00;
        public string keyValue { get; set; } = "";
    }

    /// <summary>
    /// 用于EEPROM key生成
    /// </summary>
    class Countkey
    {
        /// <summary>
        /// EepromKey的Key类型;
        /// </summary>
        public static Dictionary<string, Keyinfo> gKeydict = new Dictionary<string, Keyinfo>
        {
            { "mac", new Keyinfo{ keyType = 0x00 } },
            { "did", new Keyinfo{ keyType = 0x01 } },
            { "hdcp", new Keyinfo{ keyType =0x04 } },
            { "hdcp22", new Keyinfo{ keyType =0x05 } },
            { "widi", new Keyinfo{ keyType =0x05 } },
            { "esn", new Keyinfo{ keyType =0x07 } },
            { "widevine", new Keyinfo{ keyType =0x08 } },
            { "cikey", new Keyinfo{ keyType =0x09 } },
            { "attestation", new Keyinfo{ keyType =0x0E }},
            { "mgk", new Keyinfo{ keyType =0x0F } },
            { "playready", new Keyinfo{ keyType =0x10 }}
        };

        /// <summary>
        /// 字节数组转16进制字符串
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        private static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            if (bytes != null)
            {
                for (int i = 0; i < bytes.Length; i++)
                {
                    returnStr += bytes[i].ToString("X2");
                }
            }
            return returnStr;
        }

        public static bool Countfile(string path, string Type, out string result, out int num)
        {
            result = null;
            num = 0;
            DirectoryInfo getfile = new DirectoryInfo(path);
            foreach (FileInfo file in getfile.GetFiles())
            {
                num += 1;
                switch (Type)
                {
                    case "MAC":
                        {
                            if (file.Length != 6)
                            {
                                result = file.FullName.ToString() + "length don't match MAC 6 byte rules";
                                return false;
                            }
                            break;

                        }
                    case "DID":
                        {
                            if (file.Length != 40)
                            {
                                result = file.FullName.ToString() + "length don't match DID 40 byte rules";
                                return false;
                            }
                            break;
                        }
                    case "ESN":
                        {
                            if (file.Length != 140)
                            {
                                result = file.FullName.ToString() + "length don't match ESN 140 byte rules";
                                return false;
                            }
                            break;
                        }
                    case "burning key":
                        {
                            if (file.Length != 224)
                            {
                                result = file.FullName.ToString() + "length don't match burning key 224 byte rules";
                                return false;
                            }
                            break;
                        }
                    default:
                        {
                            result = "Can find the key type";
                            break;
                        }

                }
            }
            return true;
        }

        static byte[] head1 = { 0x03, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x06 };
        static byte[] head2 = { 0x01, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x28 };
        static byte[] head3 = { 0x07, 0x00, 0x00, 0x00, 0x54, 0x00, 0x8C };
        static byte[] FirstAddress = { 0x00, 0x00, 0x00, 0x26 };

        public static bool Conver2Dirct(string keys, out int countNotEmpty, out Dictionary<string, Keyinfo> Keydict, out string keyinfo)
        {
            keyinfo = "";
            Keydict = new Dictionary<string, Keyinfo>()
            {
                { "mac", new Keyinfo{ keyType = 0x00 } },
                { "did", new Keyinfo{ keyType = 0x01 } },
                { "hdcp", new Keyinfo{ keyType =0x04 } },
                { "hdcp22", new Keyinfo{ keyType =0x05 } },
                { "widi", new Keyinfo{ keyType =0x05 } },
                { "esn", new Keyinfo{ keyType =0x07 } },
                { "widevine", new Keyinfo{ keyType =0x08 } },
                { "cikey", new Keyinfo{ keyType =0x09 } },
                { "attestation", new Keyinfo{ keyType =0x0E }},
                { "mgk", new Keyinfo{ keyType =0x0F } },
                { "playready", new Keyinfo{ keyType =0x10 }}
            };

            countNotEmpty = 0;
            try
            {
                Dictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(keys);
                foreach (var item in dict)
                {
                    if (Keydict.ContainsKey(item.Key))
                    {
                        if (item.Key.Equals("mac"))
                            Keydict[item.Key].keyValue = item.Value.Replace("-", "");
                        else
                        {
                            if ( item.Key.Equals("did"))
                                Keydict[item.Key].keyValue = byteToHexStr(Encoding.ASCII.GetBytes(item.Value));
                            else
                                Keydict[item.Key].keyValue = item.Value;
                        }

                        if (item.Value.Length > 0)
                        {
                            keyinfo += item.Key+";";
                            countNotEmpty++;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.WriteErrorLog("\r\n合成EEPROM KEY失败:\r\n" + ex.Message);
                return false;
            }

            return true;
        }

        public static bool CreateEEPROMKey(string keys, string order, out string keyinfo, out string error)
        {
            error = "";
            keyinfo = "";
            int countNotEmpty;
            Dictionary<string, Keyinfo> Keydict;
            if (!Conver2Dirct(keys, out countNotEmpty, out Keydict, out keyinfo))
                return false;

            if (Keydict.ContainsKey("widi") && Keydict.ContainsKey("hdcp22"))
            {
                if (Keydict["widi"].keyValue.Length > 0 && Keydict["widi"].keyValue.Length > 0)
                {
                    error = "Key包里面同时包含HDCP22和WiDikey，请检查！";
                    return false;
                }
            }

            try
            {
                int LengthIndex = 0x00;
                int AddressIndex = 5 + 11 * countNotEmpty;

                List<byte> eepromKeyInfo = new List<byte>();
                List<byte> eepromKeyData = new List<byte>();

                eepromKeyInfo.Add((byte)countNotEmpty);
                foreach (var Item in Keydict)
                {
                    byte[] _Keydata = null;
                    byte[] _KeyCRC = null;
                    byte[] _KeyLength = { 0x00 };
                    byte[] _KeyAddress = { 0x00 };
                    if (Item.Value.keyValue.Length > 0)
                    {
                        _Keydata = SerialInit.HexToByte(Item.Value.keyValue);
                        _KeyCRC = BitConverter.GetBytes(CRC32.GetCRC32(_Keydata));
                        Array.Reverse(_KeyCRC);
                        eepromKeyInfo.Add(Item.Value.keyType);//添加类型
                        _KeyAddress = BitConverter.GetBytes(AddressIndex + LengthIndex);
                        Array.Reverse(_KeyAddress);
                        eepromKeyInfo.AddRange(_KeyAddress);
                        _KeyLength = CommonMethod.InttoBytelist(_Keydata.Length);
                        if (_KeyLength.Length == 1)
                            _KeyLength = new byte[2] { 0x00, _KeyLength[0] };
                        eepromKeyInfo.AddRange(_KeyLength);
                        eepromKeyInfo.AddRange(_KeyCRC);
                        eepromKeyData.AddRange(_Keydata);
                        LengthIndex = _Keydata.Length;
                        AddressIndex = CommonMethod.BytelisttoInt(_KeyAddress);
                    }
                }

                // 计算eepromKeyInfo的crc
                byte[] headfile = new byte[eepromKeyInfo.Count];
                eepromKeyInfo.CopyTo(headfile);
                byte[] WholeCrc = BitConverter.GetBytes(CRC32.GetCRC32(headfile));
                Array.Reverse(WholeCrc);
                eepromKeyInfo.AddRange(WholeCrc);

                byte[] bytekeydata = new byte[eepromKeyData.Count];
                eepromKeyData.CopyTo(bytekeydata);
                eepromKeyInfo.AddRange(bytekeydata);
                byte[] burningkey = new byte[eepromKeyInfo.Count];
                eepromKeyInfo.CopyTo(burningkey);
                Savefile(burningkey, order, Keydict["mac"].keyValue + Keydict["did"].keyValue);

                return true;
            }
            catch(Exception ex)
            {
                Log.WriteErrorLog("\r\n合成EEPROM KEY失败:\r\n" + ex.Message);
                return false;
            }
        }

        public static void Savefile(byte[] data, string order, string filename)
        {
            if (Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + @"\burningkey\" + order) == false)
            {
                Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + @"\burningkey\" + order);
            }
            FileStream fs = new FileStream(AppDomain.CurrentDomain.BaseDirectory + @"\burningkey\" + order + @"\" + filename, FileMode.Create);
            fs.Write(data, 0, data.Length);
            fs.Close();
        }
    }

    /// <summary>
    /// 用于生成FireTV key
    /// </summary>
    class FireTVkey
    {
        public static bool CreateFireTVKeys(string keys, string order, out string error)
        {
            try
            {
                error = "";
                JObject jObject = JObject.Parse(keys);
                string Mac = jObject["mac"].Value<string>().Replace("-", "");
                string WifiMac = jObject["wifimac"].Value<string>().Replace("-", "");
                string BTMac = jObject["btmac"].Value<string>().Replace("-", "");
                string HDCP = jObject["hdcp"].Value<string>().Trim();
                string HDCP22 = jObject["hdcp22"].Value<string>().Trim();
                string Widevine = jObject["widevine"].Value<string>().Trim();
                //byte[] bytedata = SerialInit.HexToByte(data);
                if (Mac.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\MAC\\MAC";
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\MAC");
                    if (!LocalTxtRecord.LocalRecord(Mac, path))
                        return false;
                }
                if (WifiMac.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\WifiMac\\WifiMac";
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\WifiMac");
                    if (!LocalTxtRecord.LocalRecord(WifiMac, path))
                        return false;
                }
                if (BTMac.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\BTMac\\BTMac";
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\BTMac");
                    if (!LocalTxtRecord.LocalRecord(BTMac, path))
                        return false;
                }
                if (HDCP.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\HDCP\\" + GetMD5.GetStrMd5(HDCP);
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\HDCP");
                    if (!CommonMethod.GetCreateHexkey(path, HDCP, out error))
                        return false;
                }
                if (HDCP22.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\HDCP22\\" + GetMD5.GetStrMd5(HDCP22);
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\HDCP22");
                    if (!CommonMethod.GetCreateHexkey(path, HDCP22, out error))
                        return false;
                }
                if (Widevine.Trim().Length > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\Widevine\\" + GetMD5.GetStrMd5(Widevine);
                    CommonMethod.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\burningkey\\" + order + "\\Widevine");
                    if (!CommonMethod.GetCreateHexkey(path, Widevine, out error))
                        return false;
                }

                return true;
            }
            catch (Exception ex)
            {
                error = ex.Message;
                return false;
            }
        }
    }

}
