using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using UnityEditor;
using UnityEngine;
using Excel;
using System;
using System.Text;

public class Tools
{
    /// <summary>
    /// Excel文件存储路径
    /// </summary>
    public static string ExcelPath = Application.dataPath + "/ArtRes/Excel/";

    /// <summary>
    /// 数据结构类存储路径
    /// </summary>
    public static string DataClassPath = Application.dataPath + "/Scripts/ExcelData/DataClass/";

    /// <summary>
    /// 数据容器类存储路径
    /// </summary>
    public static string DataContainerPath = Application.dataPath + "/Scripts/ExcelData/DataContainer/";

    public static int startIndex = 4;

    /// <summary>
    /// 以配置表生成数据结构类 数据容器类  数据 
    /// </summary>
    [MenuItem("Tools/GenerateExcel")]
    private static void GenerateExcelInfo()
    {
        //判断路径是否存在
        if (!Directory.Exists(ExcelPath))
            return;

        //创建目录 已存在的目录 直接返回文件夹信息
        DirectoryInfo directory = Directory.CreateDirectory(ExcelPath);

        //获取文件夹下的 所有文件
        FileInfo[] fileInfo = directory.GetFiles();

        DataTableCollection tables;

        //筛选后缀为.xlsx的所有Excel文件
        for (int i = 0; i < fileInfo.Length; i++)
        {       
            //如果不是Excel文件 不处理
            if (fileInfo[i].Extension != ".xlsx")
                continue;
            
            //打开一个Excel文件 得到其中的所有表数据
            using (FileStream fs = fileInfo[i].Open(FileMode.Open,FileAccess.Read))
            {
                IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(fs);
                tables = reader.AsDataSet().Tables;
                fs.Close();
            }

            //遍历文件中所有表的信息
            foreach (DataTable table in tables)
            {
                //生成数据结构类
                GenerateExcelDataClass(table);

                //生成数据容器类
                GenerateExcelContainerClass(table);

                //生成数据
                GenerateExcelData(table);
            }
        }
        Debug.Log("生成成功");
        AssetDatabase.Refresh();
    }

    /// <summary>
    /// 生成数据结构类
    /// </summary>
    /// <param name="dataTable"></param>
    private static void GenerateExcelDataClass(DataTable dataTable)
    {
        //获取变量名行
        DataRow nameRow = GetvariableNameRow(dataTable);
        //获取变量类型行
        DataRow typeRow = GetvariableTypeRow(dataTable);
        //判断路径是否存在
        if (!Directory.Exists(DataClassPath))
            Directory.CreateDirectory(DataClassPath);
       
        string classString;
        //拼接字符串
        classString = "public class " + dataTable.TableName + "\n{\n";
        for (int i = 0; i < dataTable.Columns.Count; i++)
        {
            classString += "\tpublic " + typeRow[i].ToString() + " " + nameRow[i] + ";\n"; 
        }
        classString += "}";
        File.WriteAllText(DataClassPath + dataTable.TableName + ".cs", classString);
    }

    /// <summary>
    /// 生成数据容器类
    /// </summary>
    private static void GenerateExcelContainerClass(DataTable dataTable)
    {
        //获取主键索引
        int keyIndex = GetKeyIndex(dataTable);

        //获取变量类型行
        DataRow typeRow = GetvariableTypeRow(dataTable);

        //判断路径是否存在
        if (!Directory.Exists(DataContainerPath))
            Directory.CreateDirectory(DataContainerPath);

        string str;
        str = "using System.Collections.Generic;\n";
        str += "public class " + dataTable.TableName + "Container\n{\n";
        str += string.Format("\tpublic Dictionary<{0}, {1}> dataDic = new Dictionary<{2}, {3}>();\n", typeRow[keyIndex],dataTable.TableName, typeRow[keyIndex], dataTable.TableName);
        str += "}";
        File.WriteAllText(DataContainerPath + dataTable.TableName + "Container.cs", str);
    }

    /// <summary>
    /// 生成数据
    /// </summary>
    private static void GenerateExcelData(DataTable dataTable)
    {
        //判断路径是否存在
        if (!Directory.Exists(BinaryManager.BinaryDataPath))
            Directory.CreateDirectory(BinaryManager.BinaryDataPath);

        using FileStream fs = new FileStream(BinaryManager.BinaryDataPath + dataTable.TableName + ".binary", FileMode.OpenOrCreate);
        //存储数据行数
        fs.Write(BitConverter.GetBytes(dataTable.Rows.Count - 4), 0, 4);

        //存储表中的键名
        string keyName = GetvariableNameRow(dataTable)[GetKeyIndex(dataTable)].ToString();
        byte[] bytes = Encoding.UTF8.GetBytes(keyName);

        fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
        fs.Write(bytes, 0, bytes.Length);

        DataRow row;
        DataRow typeRow = GetvariableTypeRow(dataTable);
        //存储每一行数据
        for (int i = startIndex; i < dataTable.Rows.Count; i++)
        {
            row = dataTable.Rows[i];
            for (int j = 0; j < dataTable.Columns.Count; j++)
            {
                switch (typeRow[j].ToString())
                {
                    case "int":
                        Debug.Log($"当前表{dataTable.TableName},当前行列:{i}_______{j}");
                        fs.Write(BitConverter.GetBytes(int.Parse(row[j].ToString())), 0, 4);
                        break;
                    case "bool":
                        fs.Write(BitConverter.GetBytes(bool.Parse(row[j].ToString())), 0, 1);
                        break;
                    case "float":
                        fs.Write(BitConverter.GetBytes(float.Parse(row[j].ToString())), 0, 4);
                        break;
                    case "string":
                        bytes = Encoding.UTF8.GetBytes(row[j].ToString());
                        fs.Write(BitConverter.GetBytes(bytes.Length), 0, 4);
                        fs.Write(bytes, 0, bytes.Length);
                        break;
                }
            }
        }
        fs.Flush();
        fs.Close();
    }

    /// <summary>
    /// 获取变量名所在行
    /// </summary>
    /// <param name="dataTable">表</param>
    /// <returns></returns>
    private static DataRow GetvariableNameRow(DataTable dataTable)
    {
        return dataTable.Rows[0];
    }

    /// <summary>
    /// 获取变量类型所在行
    /// </summary>
    /// <param name="dataTable">表</param>
    /// <returns></returns>
    private static DataRow GetvariableTypeRow(DataTable dataTable)
    {
        return dataTable.Rows[1];
    }

    /// <summary>
    /// 获取主键所在列 的索引
    /// </summary>
    /// <param name="dataTable"></param>
    /// <returns></returns>
    private static int GetKeyIndex(DataTable dataTable)
    {
        DataRow row = dataTable.Rows[2];
        for (int i = startIndex; i < dataTable.Columns.Count; i++)
        {
            if (row[i].ToString() == "key")
            {
                return i;
            }
        }
        return 0;
    }
}
