using System;
using System.Collections.Generic;
using System.Collections;
using System.Data;
using Sugar.Enties;

namespace WebAPIBase.NetCore.BusinessCore
{
    public class FdcUnitStructure : DbContext<SystemUser>
    {
        /// <summary>
        /// 日志操作
        /// </summary>
        private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private int defaultSystemCode;

        private string connString;

        public Hashtable UnitTree = new Hashtable();

        public Hashtable GroupTree = new Hashtable();

        public Dictionary<string, FdcStation> StationList = new Dictionary<string, FdcStation>();

        public Dictionary<string, FdcFunction> FunctionList = new Dictionary<string, FdcFunction>();

        public Dictionary<int, FdcUser> FdcUserList = new Dictionary<int, FdcUser>();

        public Dictionary<string, string> FdcUserNameList = new Dictionary<string, string>();

        private static object lockobj = new object();

        private static object userLock = new object();

        private static FdcUnitStructure instance;

        public int DefaultSystemCode
        {
            get
            {
                return defaultSystemCode;
            }
            set
            {
                defaultSystemCode = value;
            }
        }

        public string ConnString => connString;

        public static FdcUnitStructure Instance
        {
            get
            {
                if (instance == null)
                {
                    throw new ApplicationException("未初始化 FdcUnitStructure");
                }
                return instance;
            }
        }

        private FdcUnitStructure()
        {
        }

        private void initSelf(string _connString)
        {
            connString = _connString;
        }

        public void InitCache()
        {
            InitUnit();
            InitSystemCode();
            InitFunction();
            InitStations();
            Info.Clear();
            FdcUserList.Clear();
            InitUserNames();
        }

        public void InitCache(string VerName, string VerMsg, string LicenceType)
        {
            new LicenceCheck().InitLicence(connString, VerName, VerMsg, LicenceType);
            InitUnit();
            InitSystemCode();
            InitFunction();
            InitStations();
            Info.Clear();
            FdcUserList.Clear();
            InitUserNames();
            LicenceCheck.DeleteInvalidFunctionStructure(VerMsg);
        }

        private void InitUnit()
        {
            string commandText = "select u.sortid,u.unitcode,u.unitname,u.parentunitcode,u.fullcode,u.unittype,u.unitname,ur.RelationCode as relacode,isnull(ur.systemcode,-1) as relasystem from unit u left join unitrelation ur on u.unitcode=ur.unitcode and ur.RelationType = '项目' and ur.SystemCode = 0 order by u.fullcode";

            DataTable dataTable = Db.Ado.GetDataTable(commandText);
            lock (lockobj)
            {
                UnitTree.Clear();
                foreach (DataRow row in dataTable.Rows)
                {
                    if (UnitTree.ContainsKey(row["unitcode"].ToString()))
                    {
                        throw new ApplicationException("组织结构初始化失败，重复的部门编码");
                    }
                    FdcUnit fdcUnit = new FdcUnit(this, row["unitcode"].ToString(), row["fullcode"].ToString(), row["unittype"].ToString(), row["parentunitcode"].ToString(), row["unitname"].ToString(), row["relacode"].ToString(), (int)row["relasystem"]);
                    fdcUnit.SortId = row["sortid"].ToString();
                    UnitTree.Add(fdcUnit.UnitCode, fdcUnit);
                }
                foreach (DictionaryEntry item in UnitTree)
                {
                    foreach (DictionaryEntry item2 in UnitTree)
                    {
                        if (((FdcUnit)item.Value).ParentCode == ((FdcUnit)item2.Value).UnitCode)
                        {
                            ((FdcUnit)item2.Value).Children.Add((FdcUnit)item.Value);
                        }
                    }
                }
            }
        }

        private void InitSystemCode()
        {
            string commandText = "select groupcode,classcode,fullid,parentcode,sortid,groupname,deep from systemgroup order by fullid";

            DataTable dataTable = Db.Ado.GetDataTable(commandText);
            lock (lockobj)
            {
                GroupTree.Clear();
                foreach (DataRow row in dataTable.Rows)
                {
                    if (GroupTree.ContainsKey(row["groupcode"].ToString()))
                    {
                        throw new ApplicationException("系统类别初始化失败，重复的类别编码");
                    }
                    FdcSystemGroup fdcSystemGroup = new FdcSystemGroup(this, row["groupcode"].ToString(), row["classcode"].ToString(), row["parentcode"].ToString(), row["fullid"].ToString(), row["groupname"].ToString());
                    fdcSystemGroup.Deep = row["deep"].ToString();
                    fdcSystemGroup.SortId = row["sortid"].ToString();
                    GroupTree.Add(fdcSystemGroup.GroupCode, fdcSystemGroup);
                }
                foreach (DictionaryEntry item in GroupTree)
                {
                    foreach (DictionaryEntry item2 in GroupTree)
                    {
                        if (((FdcSystemGroup)item.Value).ParentCode == ((FdcSystemGroup)item2.Value).GroupCode)
                        {
                            ((FdcSystemGroup)item2.Value).Children.Add((FdcSystemGroup)item.Value);
                        }
                    }
                }
                foreach (DictionaryEntry item3 in GroupTree)
                {
                    if (((FdcSystemGroup)item3.Value).Children.Count > 0)
                    {
                        ((FdcSystemGroup)item3.Value).Children.Sort();
                    }
                }
            }
        }

        private void InitStations()
        {
            string commandText = "select s.stationcode,s.stationname,s.unitcode as stationunit,\r\nsf.functionstructurecode,\r\nsfa.unitcode,sfa.isperson,\r\ngf.groupcode,gf.classcode,gf.unitcode as groupunit,gf.isperson as groupisperson\r\nfrom station s\r\nleft join stationfunction sf on s.stationcode=sf.stationcode\r\nleft join stationfunctionarea sfa on sf.stationfunctioncode=sfa.stationfunctioncode\r\nleft outer join\r\n(select  sgs.groupcode,sgs.classcode,sgs.stationcode,sgf.functionstructurecode,sgfa.unitcode,sgfa.isperson\r\nfrom systemgroupstation sgs\r\njoin systemgroupfunction sgf on sgs.systemgroupstationcode=sgf.systemgroupstationcode\r\njoin systemgroupfunctionarea sgfa on sgfa.systemgroupfunctioncode=sgf.systemgroupfunctioncode\r\n) gf on s.stationcode = gf.stationcode and sf.functionstructurecode=gf.functionstructurecode \r\norder by s.stationcode,sf.functionstructurecode,sfa.unitcode,gf.groupcode,gf.unitcode\r\n";

            DataTable dataTable = Db.Ado.GetDataTable(commandText);
            string text = "";
            string text2 = "";
            string text3 = "";
            FdcStation fdcStation = null;
            innerFunction innerFunction = null;
            bool flag = true;
            bool flag2 = true;
            lock (lockobj)
            {
                StationList.Clear();
                foreach (DataRow row in dataTable.Rows)
                {
                    if (row["stationCode"].ToString() != text)
                    {
                        text = row["stationCode"].ToString();
                        fdcStation = new FdcStation(this, text, row["stationname"].ToString());
                        fdcStation.UnitCode = row["stationunit"].ToString();
                        fdcStation.StationName = row["stationname"].ToString();
                        StationList.Add(text, fdcStation);
                        flag = true;
                    }
                    if (flag || row["functionstructurecode"].ToString() != text2)
                    {
                        flag = false;
                        text2 = row["functionstructurecode"].ToString();
                        innerFunction = new innerFunction();
                        flag2 = true;
                        innerFunction.FunctionCode = text2;
                        fdcStation.functionList.Add(text2, innerFunction);
                    }
                    if (row["unitcode"] != DBNull.Value && (flag2 || text3 != row["unitcode"].ToString()))
                    {
                        flag2 = false;
                        text3 = row["unitcode"].ToString();
                        FdcUnitRight fdcUnitRight = new FdcUnitRight();
                        fdcUnitRight.unit = GetUnitByCode(text3);
                        if (fdcUnitRight == null)
                        {
                            continue;
                        }
                        fdcUnitRight.IsPerson = (int)row["isperson"];
                        innerFunction.UnitList.Add(fdcUnitRight);
                    }
                    if (row["groupcode"] == DBNull.Value)
                    {
                        continue;
                    }
                    FdcGroupUnitRight fdcGroupUnitRight = new FdcGroupUnitRight();
                    fdcGroupUnitRight.unit = GetUnitByCode(row["groupunit"].ToString());
                    if (fdcGroupUnitRight.unit != null)
                    {
                        fdcGroupUnitRight.group = GetGroupByCode(row["groupcode"].ToString());
                        if (fdcGroupUnitRight.group != null)
                        {
                            fdcGroupUnitRight.IsPerson = (int)row["groupisperson"];
                            innerFunction.GroupUnitList.Add(fdcGroupUnitRight);
                        }
                    }
                }
                string commandText2 = "select stationcode,unitcode,isperson from stationarea";

                DataTable dataTable2 = Db.Ado.GetDataTable(commandText2);
                foreach (KeyValuePair<string, FdcStation> station in StationList)
                {
                    FdcStation value = station.Value;
                    DataRow[] array = dataTable2.Select("stationcode='" + value.StationCode + "'");
                    foreach (DataRow dataRow in array)
                    {
                        bool flag3 = false;
                        foreach (FdcUnitRight unit in value.unitList)
                        {
                            if (unit.unit.UnitCode == dataRow["unitcode"].ToString() && unit.IsPerson == (int)dataRow["isperson"])
                            {
                                flag3 = true;
                                break;
                            }
                        }
                        if (!flag3)
                        {
                            FdcUnitRight current = new FdcUnitRight();
                            current.unit = GetUnitByCode(dataRow["unitcode"].ToString());
                            if (current.unit != null)
                            {
                                current.IsPerson = (int)dataRow["isperson"];
                                value.unitList.Add(current);
                            }
                        }
                    }
                }
                string commandText3 = "select stationcode,usercode from stationuser";

                DataTable dataTable3 = Db.Ado.GetDataTable(commandText3);
                foreach (DataRow row2 in dataTable3.Rows)
                {
                    foreach (KeyValuePair<string, FdcStation> station2 in StationList)
                    {
                        if (station2.Key == row2["stationcode"].ToString())
                        {
                            station2.Value.UserList.Add(int.Parse(row2["usercode"].ToString()));
                            break;
                        }
                    }
                }
                foreach (KeyValuePair<string, FdcStation> station3 in StationList)
                {
                    GetUnitByCode(station3.Value.UnitCode)?.StationList.Add(station3.Value);
                }
            }
        }

        private void InitUserNames()
        {
            string commandText = "select usercode,username from systemuser";

            DataTable dataTable = Db.Ado.GetDataTable(commandText);
            lock (lockobj)
            {
                FdcUserNameList.Clear();
                foreach (DataRow row in dataTable.Rows)
                {
                    FdcUserNameList.Add(row["usercode"].ToString(), row["username"].ToString());
                }
            }
        }

        private void InitFunction()
        {
            try
            {
                string commandText = "select FunctionStructureCode,FunctionStructureName,ParentCode,Deep,IsSystemClass,RightLimitPoint  from functionstructure where IsAvailable=0 order by systemcode,functionstructurecode ";

                DataTable dataTable = Db.Ado.GetDataTable(commandText);
                object obj = new object();
                lock (obj)
                {
                    FunctionList.Clear();
                    foreach (DataRow row in dataTable.Rows)
                    {
                        if (FunctionList.ContainsKey(row["functionstructurecode"].ToString()))
                        {
                            throw new ApplicationException("系统功能树初始化失败，重复的功能编码:" + row["functionstructurecode"].ToString());
                        }
                        FdcFunction fdcFunction = new FdcFunction();
                        fdcFunction.FunctionStructureCode = row["FunctionStructureCode"].ToString();
                        fdcFunction.FunctionStructureName = row["FunctionStructureName"].ToString();
                        fdcFunction.ParentCode = row["parentcode"].ToString();
                        fdcFunction.Deep = (int)row["Deep"];
                        fdcFunction.RightLimitPoint = (int)row["RightLimitPoint"];
                        FunctionList.Add(fdcFunction.FunctionStructureCode, fdcFunction);
                    }
                }
            }
            catch (Exception exp)
            {
                logger.Error(exp);
                throw;
            }
        }

        public FdcUnit GetUnitByCode(string unitCode)
        {
            if (unitCode == null)
            {
                throw new ArgumentException("错误的部门编码，不能为空值");
            }
            if (UnitTree.ContainsKey(unitCode))
            {
                return (FdcUnit)UnitTree[unitCode];
            }
            return null;
        }

        public FdcUnit GetUnitByRela(string relaCode, int systemcode)
        {
            if (relaCode == null)
            {
                throw new ArgumentException("错误的部门/项目编码，不能为空值");
            }
            foreach (DictionaryEntry item in UnitTree)
            {
                if (((FdcUnit)item.Value).RelSystem == systemcode && ((FdcUnit)item.Value).RelaCode == relaCode)
                {
                    return (FdcUnit)item.Value;
                }
            }
            return null;
        }

        public FdcSystemGroup GetGroupByCode(string groupCode)
        {
            if (GroupTree.ContainsKey(groupCode))
            {
                return (FdcSystemGroup)GroupTree[groupCode];
            }
            logger.Error("错误的系统类别编码:" + groupCode);
            return null;
        }

        public FdcStation GetStationByCode(string stationCode)
        {
            if (StationList.ContainsKey(stationCode))
            {
                return StationList[stationCode];
            }
            logger.Error("错误的岗位编码:" + stationCode);
            return null;
        }

        public FdcFunction GetFunctionByCode(string functionCode)
        {
            if (FunctionList.ContainsKey(functionCode))
            {
                return FunctionList[functionCode];
            }
            return null;
        }

        public FdcUser GetFdcUserByCode(int userCode)
        {
            lock (userLock)
            {
                if (!FdcUserList.ContainsKey(userCode))
                {
                    FdcUser value = new FdcUser(userCode.ToString());
                    FdcUserList.Add(userCode, value);
                }
            }
            return FdcUserList[userCode];
        }

        public string GetUserNameByCode(string userCode)
        {
            lock (lockobj)
            {
                if (FdcUserNameList.ContainsKey(userCode))
                {
                    return FdcUserNameList[userCode];
                }
            }
            return "";
        }

        public List<FdcStation> GetStationBySystemGroup(string systemgroupcode, string functioncode)
        {
            return null;
        }

        public List<FdcUser> GetUserByStation(FdcStation station)
        {
            return null;
        }

        public List<FdcUser> GetUserByStationList(List<FdcStation> stationlist)
        {
            return null;
        }

        public static void Init(string connString)
        {
            if (instance == null)
            {
                instance = new FdcUnitStructure();
            }
            instance.initSelf(connString);
        }
    }
}
