using Newtonsoft.Json;
using NKC_SDK;
using SteamWare;
using System.Globalization;

namespace AppData
{
    public class DataLayer
    {
        #region Public Fields

        public DS_AppTableAdapters.BatchListTableAdapter taBL;
        public DS_AppTableAdapters.BinsTableAdapter taBN;
        public DS_AppTableAdapters.BinListTableAdapter taBNLS;
        public DS_AppTableAdapters.CartsTableAdapter taCL;
        public DS_AppTableAdapters.CartOnKitTableAdapter taCOK;
        public DS_AppTableAdapters.CountersTableAdapter taCount;
        public DS_AppTableAdapters.CartsTableAdapter taCR;
        public DS_AppTableAdapters.ErrorsLogTableAdapter taEL;
        public DS_ReportTableAdapters.ElencoPostazioniTableAdapter taElPos;
        public DS_AppTableAdapters.FileValidationTableAdapter taFV;
        public DS_AppTableAdapters.ItemListTableAdapter taIL;
        public DS_AppTableAdapters.ImportLogTableAdapter taImpLog;
        public DS_AppTableAdapters.ItemSearchDetailTableAdapter taISD;
        public DS_AppTableAdapters.ItemValidationTableAdapter taIV;
        public DS_AppTableAdapters.KitListTableAdapter taKL;
        public DS_AppTableAdapters.MaterialsTableAdapter taMat;
        public DS_AppTableAdapters.NestingTableAdapter taNest;
        public DS_AppTableAdapters.OfflineOrderListTableAdapter taOffOL;
        public DS_AppTableAdapters.OKIBTableAdapter taOKIB;
        public DS_AppTableAdapters.OKIB_SumTableAdapter taOKIB_Sum;
        public DS_AppTableAdapters.OKOITableAdapter taOKOI;
        public DS_AppTableAdapters.OKOI_sumTableAdapter taOKOI_Sum;
        public DS_AppTableAdapters.OrderListTableAdapter taOL;
        public DS_AppTableAdapters.OrderListTreeTableAdapter taOLT;
        public DS_AppTableAdapters.OffOrd2ItemTableAdapter taOO2I;
        public DS_AppTableAdapters.OtherItemTableAdapter taOtItem;
        public DS_ReportTableAdapters.PrintJobQueueTableAdapter taPJQ;
        public DS_AppTableAdapters.PackListTableAdapter taPL;
        public DS_AppTableAdapters.PlacesTableAdapter taPlac;
        public DS_AppTableAdapters.PackCheckTableAdapter taPLC;
        public DS_AppTableAdapters.PackListDetTableAdapter taPLD;
        public DS_AppTableAdapters.PackLogTableAdapter taPLog;
        public DS_AppTableAdapters.PartValidParetoTableAdapter taPVP;
        public DS_AppTableAdapters.RemnantsTableAdapter taRem;
        public DS_ReportTableAdapters.stp_prt_BinTableAdapter taRepBin;
        public DS_ReportTableAdapters.stp_prt_BunkGroupTableAdapter taRepBunkGroup;
        public DS_ReportTableAdapters.stp_prt_BunkListTableAdapter taRepBunkList;
        public DS_ReportTableAdapters.stp_prt_CartTableAdapter taRepCart;
        public DS_ReportTableAdapters.stp_prt_IRKTableAdapter taRepIRK;
        public DS_ReportTableAdapters.stp_prt_IRK_SumTableAdapter taRepIRKSum;
        public DS_ReportTableAdapters.stp_prt_OtherPartTableAdapter taRepOtherPart;
        public DS_ReportTableAdapters.stp_prt_PartTableAdapter taRepPart;
        public DS_AppTableAdapters.SheetListTableAdapter taSHL;
        public DS_AppTableAdapters.SheetsPreviewTableAdapter taSP;
        public DS_AppTableAdapters.StatusDecodeTableAdapter taStatDec;
        public DS_AppTableAdapters.StatusLogTableAdapter taStatLog;
        public DS_AppTableAdapters.StackListTableAdapter taSTL;
        public DS_AppTableAdapters.UnloadStatsTableAdapter taUS;
        public DS_AppTableAdapters.UpdManTableAdapter taUpdMan;

        #endregion Public Fields

        #region Public Constructors

        public DataLayer()
        {
            // inizializzaizone classe
            initTA();
            setupConnString();
            cacheDataTTL = memLayer.ML.CRI("cacheDataTTL");
        }

        #endregion Public Constructors

        #region Protected Properties

        protected int cacheDataTTL { get; set; } = 2;

        #endregion Protected Properties

        #region Public Properties

        public string CodSoggCurrUser
        {
            get
            {
                return "O000123456";
            }
        }

        public string CognNomeCurrUser
        {
            get
            {
                return "Mario Rossi";
            }
        }

        #endregion Public Properties

        #region Private Methods

        /// <summary>
        /// verifica esistenza record da tipo doc + chiave...
        /// </summary>
        /// <param name="tipoDoc"></param>
        /// <param name="keyParam"></param>
        /// <returns></returns>
        private bool checkDoc(tipoDocumento tipoDoc, string keyParam)
        {
            bool answ = false;
            int intIdx = 0;
            switch (tipoDoc)
            {
                case tipoDocumento.docBinPre:
                case tipoDocumento.docBinPost:
                    int.TryParse(keyParam, out intIdx);
                    var tabBinPre = taBN.getByKey(intIdx);
                    answ = tabBinPre.Count > 0;
                    break;

                case tipoDocumento.docCart:
                case tipoDocumento.docCartIRK:
                case tipoDocumento.docCartIRKSum:
                    int.TryParse(keyParam, out intIdx);
                    var tabCarts = taCR.getByKey(intIdx);
                    answ = tabCarts.Count > 0;
                    break;

                case tipoDocumento.docPart:
                    int.TryParse(keyParam, out intIdx);
                    var tabPart = taIL.getByKey(intIdx);
                    answ = tabPart.Count > 0;
                    break;

                case tipoDocumento.docOtherPart:
                    int.TryParse(keyParam, out intIdx);
                    var tabOtherPart = taOtItem.getByKey(intIdx);
                    answ = tabOtherPart.Count > 0;
                    break;

                case tipoDocumento.docStack:
                    int.TryParse(keyParam, out intIdx);
                    var tabStack = taSTL.getByKey(intIdx);
                    answ = tabStack.Count > 0;
                    break;

                case tipoDocumento.docND:
                    break;

                default:
                    break;
            }
            return answ;
        }

        private void initTA()
        {
            taBL = new DS_AppTableAdapters.BatchListTableAdapter();
            taBN = new DS_AppTableAdapters.BinsTableAdapter();
            taBNLS = new DS_AppTableAdapters.BinListTableAdapter();
            taCL = new DS_AppTableAdapters.CartsTableAdapter();
            taCOK = new DS_AppTableAdapters.CartOnKitTableAdapter();
            taCount = new DS_AppTableAdapters.CountersTableAdapter();
            taCR = new DS_AppTableAdapters.CartsTableAdapter();
            taEL = new DS_AppTableAdapters.ErrorsLogTableAdapter();
            taFV = new DS_AppTableAdapters.FileValidationTableAdapter();
            taIL = new DS_AppTableAdapters.ItemListTableAdapter();
            taImpLog = new DS_AppTableAdapters.ImportLogTableAdapter();
            taISD = new DS_AppTableAdapters.ItemSearchDetailTableAdapter();
            taIV = new DS_AppTableAdapters.ItemValidationTableAdapter();
            taKL = new DS_AppTableAdapters.KitListTableAdapter();
            taMat = new DS_AppTableAdapters.MaterialsTableAdapter();
            taNest = new DS_AppTableAdapters.NestingTableAdapter();
            taOffOL = new DS_AppTableAdapters.OfflineOrderListTableAdapter();
            taOO2I = new DS_AppTableAdapters.OffOrd2ItemTableAdapter();
            taOKIB = new DS_AppTableAdapters.OKIBTableAdapter();
            taOKIB_Sum = new DS_AppTableAdapters.OKIB_SumTableAdapter();
            taOKOI = new DS_AppTableAdapters.OKOITableAdapter();
            taOKOI_Sum = new DS_AppTableAdapters.OKOI_sumTableAdapter();
            taOL = new DS_AppTableAdapters.OrderListTableAdapter();
            taOLT = new DS_AppTableAdapters.OrderListTreeTableAdapter();
            taOtItem = new DS_AppTableAdapters.OtherItemTableAdapter();
            taPL = new DS_AppTableAdapters.PackListTableAdapter();
            taPlac = new DS_AppTableAdapters.PlacesTableAdapter();
            taPLC = new DS_AppTableAdapters.PackCheckTableAdapter();
            taPLD = new DS_AppTableAdapters.PackListDetTableAdapter();
            taPLog = new DS_AppTableAdapters.PackLogTableAdapter();
            taPVP = new DS_AppTableAdapters.PartValidParetoTableAdapter();
            taRem = new DS_AppTableAdapters.RemnantsTableAdapter();
            taStatDec = new DS_AppTableAdapters.StatusDecodeTableAdapter();
            taStatLog = new DS_AppTableAdapters.StatusLogTableAdapter();
            taSTL = new DS_AppTableAdapters.StackListTableAdapter();
            taSHL = new DS_AppTableAdapters.SheetListTableAdapter();
            taSP = new DS_AppTableAdapters.SheetsPreviewTableAdapter();
            taElPos = new DS_ReportTableAdapters.ElencoPostazioniTableAdapter();
            taPJQ = new DS_ReportTableAdapters.PrintJobQueueTableAdapter();
            taRepBin = new DS_ReportTableAdapters.stp_prt_BinTableAdapter();
            taRepBunkGroup = new DS_ReportTableAdapters.stp_prt_BunkGroupTableAdapter();
            taRepBunkList = new DS_ReportTableAdapters.stp_prt_BunkListTableAdapter();
            taRepCart = new DS_ReportTableAdapters.stp_prt_CartTableAdapter();
            taRepPart = new DS_ReportTableAdapters.stp_prt_PartTableAdapter();
            taRepOtherPart = new DS_ReportTableAdapters.stp_prt_OtherPartTableAdapter();
            taRepIRK = new DS_ReportTableAdapters.stp_prt_IRKTableAdapter();
            taRepIRKSum = new DS_ReportTableAdapters.stp_prt_IRK_SumTableAdapter();
            taUS = new DS_AppTableAdapters.UnloadStatsTableAdapter();
            taUpdMan = new DS_AppTableAdapters.UpdManTableAdapter();
        }

        private void setupConnString()
        {
            string connString = memLayer.ML.CRS("NKC_WFConnectionString");
            taBL.Connection.ConnectionString = connString;
            taBN.Connection.ConnectionString = connString;
            taBNLS.Connection.ConnectionString = connString;
            taCL.Connection.ConnectionString = connString;
            taCOK.Connection.ConnectionString = connString;
            taCount.Connection.ConnectionString = connString;
            taCR.Connection.ConnectionString = connString;
            taEL.Connection.ConnectionString = connString;
            taFV.Connection.ConnectionString = connString;
            taIL.Connection.ConnectionString = connString;
            taImpLog.Connection.ConnectionString = connString;
            taISD.Connection.ConnectionString = connString;
            taIV.Connection.ConnectionString = connString;
            taKL.Connection.ConnectionString = connString;
            taMat.Connection.ConnectionString = connString;
            taNest.Connection.ConnectionString = connString;
            taOffOL.Connection.ConnectionString = connString;
            taOO2I.Connection.ConnectionString = connString;
            taOKIB.Connection.ConnectionString = connString;
            taOKIB_Sum.Connection.ConnectionString = connString;
            taOKOI.Connection.ConnectionString = connString;
            taOKOI_Sum.Connection.ConnectionString = connString;
            taOL.Connection.ConnectionString = connString;
            taOLT.Connection.ConnectionString = connString;
            taOtItem.Connection.ConnectionString = connString;
            taPL.Connection.ConnectionString = connString;
            taPlac.Connection.ConnectionString = connString;
            taPLC.Connection.ConnectionString = connString;
            taPLD.Connection.ConnectionString = connString;
            taPLog.Connection.ConnectionString = connString;
            taPVP.Connection.ConnectionString = connString;
            taRem.Connection.ConnectionString = connString;
            taStatDec.Connection.ConnectionString = connString;
            taStatLog.Connection.ConnectionString = connString;
            taSTL.Connection.ConnectionString = connString;
            taSHL.Connection.ConnectionString = connString;
            taSP.Connection.ConnectionString = connString;
            taElPos.Connection.ConnectionString = connString;
            taPJQ.Connection.ConnectionString = connString;
            taRepBin.Connection.ConnectionString = connString;
            taRepBunkGroup.Connection.ConnectionString = connString;
            taRepBunkList.Connection.ConnectionString = connString;
            taRepCart.Connection.ConnectionString = connString;
            taRepPart.Connection.ConnectionString = connString;
            taRepOtherPart.Connection.ConnectionString = connString;
            taRepIRK.Connection.ConnectionString = connString;
            taRepIRKSum.Connection.ConnectionString = connString;
            taUS.Connection.ConnectionString = connString;
            taUpdMan.Connection.ConnectionString = connString;
        }

        #endregion Private Methods

        #region Public Methods

        /// <summary>
        /// Main BCode decoding function
        /// </summary>
        /// <param name="bcValue"></param>
        /// <returns></returns>
        public decodedData decodeBcode(string bcValue)
        {
            decodedData answ = new decodedData();
            answ.rawData = bcValue;
            if (bcValue.StartsWith("MT"))
            {
                answ.codeType = codeType.Material;
                answ.code = bcValue.Replace("MT", "");
                int codeInt = 0;
                int.TryParse(answ.code, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"Material: {answ.code}";
            }
            else if (bcValue.StartsWith("SSC"))
            {
                answ.codeType = codeType.SecScreen;
                answ.code = bcValue.Replace("SSC", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"Secondary Screen : {answ.code}";
            }
            else if (bcValue.StartsWith("BK"))
            {
                answ.codeType = codeType.Stack;
                answ.code = bcValue.Replace("BK", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"BUNK: {answ.code}";
            }
            else if (bcValue.StartsWith("IG"))
            {
                answ.codeType = codeType.ItemGeneric;
                answ.code = bcValue.Replace("IG", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"Item Generic: {answ.code}";
            }
            else if (bcValue.StartsWith("IX"))
            {
                answ.codeType = codeType.OtherItem;
                answ.code = bcValue.Replace("IX", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("OtherPart")}: {answ.code}";
            }
            else if (bcValue.StartsWith("IT"))
            {
                answ.codeType = codeType.Item;
                answ.code = bcValue.Replace("IT", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("Part")}: {answ.code}";
            }
            else if (bcValue.StartsWith("CR"))
            {
                answ.codeType = codeType.Cart;
                answ.code = bcValue.Replace("CR", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("Cart")}: {answ.code}";
            }
            else if (bcValue.StartsWith("BN"))
            {
                answ.codeType = codeType.Bin;
                answ.code = bcValue.Replace("BN", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("Bin")}: {answ.code}";
            }
            else if (bcValue.StartsWith("BP"))
            {
                answ.codeType = codeType.BinProcessed;
                answ.code = bcValue.Replace("BP", "");
                int codeInt = 0;
                int.TryParse(answ.code, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codeInt);
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("BinPaint")}: {answ.code}";
            }
            else if (bcValue.StartsWith("MSEL"))
            {
                answ.codeType = codeType.MachSelection;
                answ.code = bcValue.Replace("MSEL", "");
                int codeInt = 0;
                answ.codeInt = codeInt;
                answ.description = $"{ComLib.traduci("BinPaint")}: {answ.code}";
            }
            return answ;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
        public DS_App.BinsDataTable getBinByBatch(int BatchID)
        {
            DS_App.BinsDataTable answ = new DS_App.BinsDataTable();
            // controllo cache
            bool trovato = false;
            string redKey = memLayer.ML.redHash($"BinByBatch:{BatchID}");
            string rawData = "";
            rawData = memLayer.ML.getRSV(redKey);
            if (!string.IsNullOrEmpty(rawData))
            {
                try
                {
                    answ = JsonConvert.DeserializeObject<DS_App.BinsDataTable>(rawData);
                    trovato = true;
                }
                catch
                { }
            }
            if (!trovato)
            {
                // se non trovo leggo
                answ = taBN.getByBatch(BatchID);
                rawData = JsonConvert.SerializeObject(answ);
                // salvo in redis
                memLayer.ML.setRSV(redKey, rawData, cacheDataTTL);
            }

            //restituisco valore..
            return answ;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
        public DS_App.CartsDataTable getCartByBatch(int BatchID)
        {
            DS_App.CartsDataTable answ = new DS_App.CartsDataTable();
            // controllo cache
            bool trovato = false;
            string redKey = memLayer.ML.redHash($"CartByBatch:{BatchID}");
            string rawData = "";
            rawData = memLayer.ML.getRSV(redKey);
            if (!string.IsNullOrEmpty(rawData))
            {
                try
                {
                    answ = JsonConvert.DeserializeObject<DS_App.CartsDataTable>(rawData);
                    trovato = true;
                }
                catch
                { }
            }
            if (!trovato)
            {
                // se non trovo leggo
                answ = taCL.getByBatch(BatchID);
                rawData = JsonConvert.SerializeObject(answ);
                // salvo in redis
                memLayer.ML.setRSV(redKey, rawData, cacheDataTTL);
            }

            //restituisco valore..
            return answ;
        }

        /// <summary>
        /// Recupera printer dato codPostazione
        /// </summary>
        /// <param name="codPost"></param>
        /// <returns></returns>
        public string getPrinter(string codPost)
        {
            string printer = "";
            // recupero da DB...
            try
            {
                DataLayer DLMan = new DataLayer();
                var tabPost = DLMan.taElPos.getByKey(codPost);
                if (tabPost.Count == 1)
                {
                    printer = tabPost[0].stampante;
                }
            }
            catch
            { }
            return printer;
        }

        [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
        public DS_App.UnloadStatsDataTable getUnloadStatsByBatch(int BatchID, int StatLevel)
        {
            DS_App.UnloadStatsDataTable answ = new DS_App.UnloadStatsDataTable();
            // controllo cache
            bool trovato = false;
            string redKey = memLayer.ML.redHash($"UnloadStatsByBatch:{BatchID}:{StatLevel}");
            string rawData = "";
            rawData = memLayer.ML.getRSV(redKey);
            if (!string.IsNullOrEmpty(rawData))
            {
                try
                {
                    answ = JsonConvert.DeserializeObject<DS_App.UnloadStatsDataTable>(rawData);
                    trovato = true;
                }
                catch
                { }
            }
            if (!trovato)
            {
                // se non trovo leggo
                answ = taUS.GetData(BatchID, StatLevel);
                rawData = JsonConvert.SerializeObject(answ);
                // salvo in redis
                memLayer.ML.setRSV(redKey, rawData, cacheDataTTL);
            }

            //restituisco valore..
            return answ;
        }

        /// <summary>
        /// effettua la stampa di un documento
        /// </summary>
        /// <param name="keyParam">Codice UNIVOCO del documento</param>
        /// <param name="printer">stampante specifica (da postazione o std da web.config, a cura dell'utente</param>
        /// <param name="tipoDoc">Tipo documento richiesto</param>
        /// <param name="clientIp">IP del chiamante</param>
        /// <returns></returns>
        public bool stampaDoc(string keyParam, string printer, tipoDocumento tipoDoc, string clientIp)
        {
            bool answ = false;
            // controllo se esista DOC
            if (checkDoc(tipoDoc, keyParam))
            {
                answ = reportPrinter.obj.stampaCartellino(tipoDoc, keyParam, printer, true);
                // svuoto code redis salvate..
                memLayer.ML.redFlushKey(ComLib.redQueueCount);
                memLayer.ML.redFlushKey(ComLib.redQueueCountSet);
                if (answ)
                {
                    logger.lg.scriviLog(string.Format(" | {0} | stampato UDC {1} | stampante {2} | tipo {3}", clientIp, keyParam, printer, tipoDoc), tipoLog.INFO);
                }
                else
                {
                    logger.lg.scriviLog(string.Format("ERRORE | {0} | stampato UDC {1} | stampante {2} | tipo {3}", clientIp, keyParam, printer, tipoDoc), tipoLog.ERROR);
                }
            }
            else
            {
                logger.lg.scriviLog(string.Format(" | {0} | Richiesta stampa per DOC tipo {1} | stampante {2} | key {3}", clientIp, tipoDoc, printer, keyParam), tipoLog.ERROR);
            }
            return answ;
        }

        #endregion Public Methods
    }
}