using EIS.Framework.Service.GEM;
using JWH;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;

namespace DDUtilityApp.SECS
{

    public class SECSDefine
    {

        #region [ Properties ] ------------------------------------------------

        public string Name { get; set; }

        public Dictionary<string, CEID> CeidDictionary { get; set; } = new Dictionary<string, CEID>();

        public Dictionary<string, RPT> RptDictionary { get; set; } = new Dictionary<string, RPT>();

        public Dictionary<string, VID> VidDictionary { get; set; } = new Dictionary<string, VID>();

        public IEnumerable<CEID> CeidCollection { get { return CeidDictionary.Values; } }

        public IEnumerable<RPT> RptCollection { get { return RptDictionary.Values; } }

        public IEnumerable<VID> VidCollection { get { return VidDictionary.Values; } }

        #endregion

        #region [ SECSSetting ] -----------------------------------------------

        public SECSDefine()
        {
        }

        public SECSDefine(XmlNode node)
        {
            try
            {
                this.Name = node.Attributes["NAME"].Value;
                foreach (XmlNode child in node.ChildNodes)
                {
                    if (string.Compare(child.Name, "CEID_LIST", true) == 0) this.Load_CEID(child);
                    else if (string.Compare(child.Name, "RPT_LIST", true) == 0) this.Load_RPT(child);
                }
                this.VidDictionary = this.GetVidDictionary();

                Trace.WriteLine($"  <MODEL NAME='{this.Name}'>");
                Trace.WriteLine($"    <CEID_LIST>");
                foreach (CEID ceid in this.CeidCollection.OrderBy(x => x.ID))
                    Trace.WriteLine($"{ceid.ToXml("      ")}");
                Trace.WriteLine($"    </CEID_LIST>");

                Trace.WriteLine($"    <RPT_LIST>");
                foreach (RPT rpt in this.RptCollection.OrderBy(x => x.ID))
                    Trace.WriteLine($"{rpt.ToXml("      ")}");
                Trace.WriteLine($"    </RPT_LIST>");

                Trace.WriteLine($"    <VID_LIST>");
                foreach (VID vid in this.VidCollection.OrderBy(x => x.ID))
                    Trace.WriteLine($"{vid.ToXml("      ")}");
                Trace.WriteLine($"    </VID_LIST>");
                Trace.WriteLine($"  </MODEL>");

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }
        }

        public SECSDefine(EIS.Framework.Service.GEM.GEMSettings gem)
        {
            try
            {
                foreach (VIDInfo gemVid in gem.VIDList.Values)
                {
                    VID vid = new VID(gemVid.ID, gemVid.Name, gemVid.Class.ToString(), "", gemVid.Description);
                    this.VidDictionary.Add(vid.ID, vid);
                    //Trace.WriteLine($"<VID ID='{gemVid.ID}' NAME='{gemVid.Name}' CLASS='{gemVid.Class}' DESCRIPTION='{gemVid.Description}' />");
                }

                foreach (RPTIDInfo gemRpt in gem.RPTIDList.Values)
                {
                    RPT rpt = new RPT(gemRpt.ID, "", gemRpt.Description);
                    this.RptDictionary.Add(rpt.ID, rpt);

                    int vidSeq = 1;
                    foreach (string strVid in gemRpt.VIDList)
                    {
                        VID vid = this.VidDictionary[strVid].Clone();
                        vid.Seq = vidSeq++;
                        rpt.VidDictionary.Add(strVid, vid);
                    }
                    //Trace.WriteLine($"<RPT ID='{gemRpt.ID}'>");
                    //foreach (string vID in gemRpt.VIDList)
                    //    Trace.WriteLine($"  <VID ID='{vID}' />");
                    //Trace.WriteLine($"</RPT>");
                }

                foreach (CEIDInfo gemCeid in gem.CEIDList.Values)
                {
                    CEID ceid = new CEID(gemCeid.ID, gemCeid.Name, gemCeid.Description, gemCeid.Enable);
                    this.CeidDictionary.Add(ceid.ID, ceid);

                    int rptSeq = 1;
                    foreach (string strRpt in gemCeid.RPTIDList)
                    {
                        RPT rpt = this.RptDictionary[strRpt].Clone();
                        rpt.Seq = rptSeq++;
                        ceid.RptDictionary.Add(rpt.ID, rpt);
                    }
                    //Trace.WriteLine($"<CEID ID='{gemCeid.ID}' NAME='{gemCeid.Name}' ENABLE='{gemCeid.Enable}' DESCRIPTION='{gemCeid.Description}'>");
                    //foreach (string rptID in gemCeid.RPTIDList)
                    //    Trace.WriteLine($"  <RPT ID='{rptID}' />");
                    //Trace.WriteLine($"</CEID>");
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }
        }

        #endregion

        #region [ Method ] ----------------------------------------------------

        private void Load_CEID(XmlNode root)
        {
            try
            {
                CEID ceid = null;
                foreach (XmlNode node in root.ChildNodes)
                {
                    ceid = CEID.CreateCEID(node);
                    if (ceid != null)
                    {
                        if (this.CeidDictionary.ContainsKey(ceid.ID))
                            XLogger.Instance.Warn($"CEID.ID={ceid.ID} 가 이미 존재합니다.");
                        else
                            this.CeidDictionary.Add(ceid.ID, ceid);
                    }
                    else
                    {
                        XLogger.Instance.Warn($"CEID를 생성하지 못하였습니다.");
                    }
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }
        }

        private void Load_RPT(XmlNode root)
        {
            try
            {
                RPT rpt = null;
                foreach (XmlNode node in root.ChildNodes)
                {
                    rpt = RPT.CreateRPT(node);
                    if (rpt != null)
                    {
                        if (this.RptDictionary.ContainsKey(rpt.ID))
                            XLogger.Instance.Warn($"RPT.ID={rpt.ID} 가 이미 존재합니다.");
                        else
                            this.RptDictionary.Add(rpt.ID, rpt);
                    }
                    else
                    {
                        XLogger.Instance.Warn($"RPT를 생성하지 못하였습니다.");
                    }
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }
        }

        private Dictionary<string, VID> GetVidDictionary()
        {
            Dictionary<string, VID> dicVID = new Dictionary<string, VID>();
            try
            {
                foreach (RPT rpt in this.RptCollection)
                {
                    foreach (VID vid in rpt.VidCollection)
                    {
                        if (dicVID.ContainsKey(vid.ID)) continue;
                        dicVID.Add(vid.ID, vid);
                    }
                }

                return dicVID;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return dicVID;
            }
        }

        public void SetInformation(SECSItem item)
        {
            try
            {
                if ($"S{item.Stream}F{item.Function}" == "S6F11")
                {
                    if (item.ChildItems.Count != 3)
                    {
                        XLogger.Instance.Warn($"S6F11 하위 항목의 갯수가 일치하지 않습니다.");
                        return;
                    }

                    if (string.IsNullOrEmpty(item.ChildItems[0].Name)) item.ChildItems[0].Name = "DATAID";
                    if (string.IsNullOrEmpty(item.ChildItems[1].Name)) item.ChildItems[1].Name = "CEID";
                    if (!this.CeidDictionary.ContainsKey(item.ChildItems[1].Value))
                    {
                        XLogger.Instance.Warn($"CEID={item.ChildItems[1].Value}가 정의되지 않았습니다.");
                        return;
                    }

                    CEID ceid = this.CeidDictionary[item.ChildItems[1].Value];
                    item.ChildItems[1].Description = ceid.Name;
                    foreach (SECSItem itemRPT in item.ChildItems[2].ChildItems)
                    {
                        if (itemRPT.ChildItems.Count != 2)
                        {
                            XLogger.Instance.Warn($"CEID={item.ChildItems[1].Value}의 레포트 갯수가 일치하지 않습니다.");
                            continue;
                        }
                        if (string.IsNullOrEmpty(itemRPT.ChildItems[0].Name)) itemRPT.ChildItems[0].Name = "RPTID";
                        if (!this.RptDictionary.ContainsKey(itemRPT.ChildItems[0].Value))
                        {
                            XLogger.Instance.Warn($"RPTID={itemRPT.ChildItems[0].Value}가 정의되지 않았습니다.");
                            continue;
                        }

                        RPT rpt = this.RptDictionary[itemRPT.ChildItems[0].Value];
                        if (rpt.VidDictionary.Count != itemRPT.ChildItems[1].Count)
                        {
                            XLogger.Instance.Warn($"RPTID={itemRPT.ChildItems[0].Value}의 VID 갯수가 일치하지 않습니다.");
                            continue;
                        }
                        int index = 0;
                        foreach (VID vid in rpt.VidCollection)
                        {
                            if (string.IsNullOrEmpty(itemRPT.ChildItems[1][index].Name)) itemRPT.ChildItems[1][index].Name = vid.Name;
                            if (string.IsNullOrEmpty(itemRPT.ChildItems[1][index].Description)) itemRPT.ChildItems[1][index].Description = vid.Description;
                            index++;
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }
        }

        #endregion

    }

}
