using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XRTool.Util;

namespace PublicTools.XMLDataBase
{
    /// <summary>
    /// 一个辅助读写的脚本
    /// 提供相关类型的读写操作
    /// </summary>
    public class TableHelper<T>
    {
        private TableInterface table;
        private string path;
        private List<T> dataList;
        public event Action readConfComplete;
        public bool isInit = false;
        private Dictionary<string, T> dataDic = new Dictionary<string, T>();
        private string priKey;
        /// <summary>
        /// 是否可写，默认可写
        /// </summary>
        private bool isWrite = true;

        public TableHelper(string path, string priKey = null)
        {
            this.path = path;
            this.priKey = priKey;
            readConfComplete += OnRreadConfComplete;
        }
        /// <summary>
        /// 读取完成之后
        /// </summary>
        private void OnRreadConfComplete()
        {
            if (DataList != null)
            {
                for (int i = 0; i < DataList.Count; i++)
                {
                    if (string.IsNullOrEmpty(priKey))
                    {
                        if (DataList[i] is TableBase)
                        {
                            var da = DataList[i] as TableBase;
                            if (!dataDic.ContainsKey(da.priKey))
                            {
                                dataDic.Add(da.priKey, DataList[i]);
                            }
                        }
                        else if (DataList[i] is UnityEngine.Object)
                        {
                            var da = DataList[i] as UnityEngine.Object;
                            if (!dataDic.ContainsKey(da.name))
                            {
                                dataDic.Add(da.name, DataList[i]);
                            }
                        }
                    }
                    else
                    {
                        string key = ClazzFactory.GetPriKey<T>(DataList[i], priKey);
                        if (!dataDic.ContainsKey(key))
                        {
                            dataDic.Add(key, DataList[i]);
                        }
                    }
                }
            }
            isInit = true;
        }

        public void Reset(bool isOpen = true)
        {
            if (DataList != null)
            {
                DataList.Clear();
            }
            isInit = false;
            DataList = null;
            dataDic.Clear();
            if (table != null)
            {
                table.Close();
            }
            XSql.Instance.CloseTable(typeof(T).Name);
            if (isOpen)
            {
                Open();
            }
        }
        public void Close()
        {
            if (table != null)
            {
                table.Close();
            }
            XSql.Instance.CloseTable(typeof(T).Name);
        }
        public List<T> DataList { get => dataList; set => dataList = value; }
        /// <summary>
        /// 打开指定的数据
        /// </summary>
        /// <param name="priKey"></param>
        public void Open(string priKey = null)
        {
            if (!string.IsNullOrEmpty(priKey))
            {
                this.priKey = priKey;
            }
            isWrite = true;
            ///如果路径为本地只读路径，同时是安卓平台时，要走异步处理
            if (path.StartsWith(Application.streamingAssetsPath))
            {
#if !UNITY_EDITOR
                isWrite = false;
#endif
            }
            if (isWrite)
            {
                table = XSql.Instance.OpenTable(path, typeof(T).Name, ".xml", true);
                if (!table.Open())
                {
                    table.Create(typeof(T).Name);
                }
                this.DataList = table.FindAllData<T>();
                readConfComplete?.Invoke();
            }
            else
            {
                if (TimerMgr.ForceInstance())
                {
                    string fullPath = Path.Combine(path, typeof(T).Name + ".xml");
                    TimerMgr.Instance.StartCoroutine(XSql.Instance.ReadServerData(fullPath, (List<T> scrollList) =>
                    {
                        this.DataList = scrollList;
                        readConfComplete?.Invoke();
                    }));
                }
            }
        }
        /// <summary>
        /// 添加一条配置
        /// </summary>
        /// <param name="conf"></param>
        public bool AddData(T conf, bool isSave = true)
        {
            bool isAddSucess = false;
            if (table == null)
            {
                Open(priKey);
            }
            if (table != null)
            {
                if (string.IsNullOrEmpty(priKey))
                {
                    if (conf is TableBase)
                    {
                        var tab = conf as TableBase;
                        if (table.InsertData(conf, tab.priKey))
                        {
                            if (isSave)
                                table.Save();
                            UnityLog.Log("Add Success!" + tab.priKey, 2);
                            isAddSucess = true;
                        }
                        else
                        {
                            UnityLog.LogError("Add DataConf Error!" + conf);
                        }
                    }
                    else if (conf is UnityEngine.Object)
                    {
                        var tab = conf as UnityEngine.Object;
                        if (table.InsertData(conf, tab.name))
                        {
                            if (isSave)
                                table.Save();
                            isAddSucess = true;
                            UnityLog.Log("Add Success!" + tab.name, 2);
                        }
                        else
                        {
                            UnityLog.LogError("Add DataConf Error!" + conf);
                        }
                    }
                    else
                    {
                        if (table.InsertData(conf))
                        {
                            if (isSave)
                                table.Save();
                            UnityLog.Log("Add Success!" + conf, 2);
                            isAddSucess = true;
                        }
                        else
                        {
                            //UnityLog.LogError("Add DataConf Error!" + conf);
                        }
                    }
                }
                else
                {
                    string key = ClazzFactory.GetPriKey<T>(conf, priKey);
                    if (table.InsertData(conf, key))
                    {
                        if (isSave)
                            table.Save();
                        UnityLog.Log("Add Success!" + conf + key, 2);
                        isAddSucess = true;
                    }
                    else
                    {
                        UnityLog.LogError("Add DataConf Error!" + conf);
                    }
                }


            }
            else
            {
                UnityLog.LogError("Add DataConf Error!No table" + conf);
            }
            if (isAddSucess)
            {
                if (DataList == null)
                {
                    DataList = new List<T>();
                }
                if (!DataList.Contains(conf))
                {
                    DataList.Add(conf);
                }
                if (dataDic == null)
                {
                    dataDic = new Dictionary<string, T>();
                }
                if (!dataDic.ContainsKey(priKey))
                {
                    dataDic.Add(priKey, conf);
                }
            }
            return isAddSucess;
        }
        /// <summary>
        /// 清空表格
        /// </summary>
        public void DelAll()
        {
            if (table != null)
            {
                table.DeleteAllData<T>();
                table.Save();
            }
            Reset();
        }

        /// <summary>
        /// 删除这条配置
        /// </summary>
        /// <param name="key"></param>
        public void DelConf(string key, bool isSave = true)
        {
            T t = FindData(key);
            if (t != null)
            {
                DataList.Remove(t);
                dataDic.Remove(key);
            }
            table.DeleteData<T>(key);
            if (isSave)
            {
                table.Save();
            }
        }
        public void SaveData()
        {
            table?.Save();
        }
        /// <summary>
        /// 根据key值查找数据
        /// 如果缓存列表里没有这条记录，则去循环列表中查找
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public T FindData(string name, string priKey = null)
        {
            ///按主键进行查找
            if (string.IsNullOrEmpty(priKey))
            {
                priKey = this.priKey;
            }
            if (!string.IsNullOrEmpty(name))
            {
                if (dataDic != null && dataDic.ContainsKey(name))
                {
                    return dataDic[name];
                }
                else
                {
                    ///存在主键值
                    if (!string.IsNullOrEmpty(priKey))
                    {
                        if (DataList == null || DataList.Count < 1)
                        {
                            return default(T);
                        }
                        return DataList.Find((data) =>
                        {
                            if (name == ClazzFactory.GetPriKey<T>(data, priKey))
                            {
                                return true;
                            }
                            return false;
                        });
                    }
                    else
                    {
                        ///暴力破解法，很少使用,请尽量避免使用此分支
                        UnityLog.LogError("Use Wrong method!");
                        return DataList.Find((data) =>
                        {
                            var dic = ClazzFactory.ClazzAnalyze<T>(data);
                            if (dic != null)
                            {
                                foreach (var item in dic)
                                {
                                    if (item.Value == name)
                                    {
                                        return true;
                                    }
                                }
                            }
                            return false;
                        });
                    }
                }
            }
            return default;
        }
    }
}