using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using MapoSDK;
using Newtonsoft.Json;
using Opc.Ua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading.Tasks;
using static IOB_UT_NEXT.CustomObj;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace IOB_WIN_OPC_UA.IobOpc
{
    public class OpcUaKpwRama : OpcUaKpw
    {
        #region Public Constructors

        /// <summary>
        /// Estende l'init della classe base, impiegando il pacchetto Nuget OPC-UA foundation con la
        /// gestione specifica per adapter KepWare OPC-UA (es RAMA RED by Unitech x TFT) 
        /// https://github.com/OPCFoundation/UA-.NETStandard
        /// </summary>
        /// <param name="caller">Form chiamante</param>
        /// <param name="IOBConf">Configurazione (legacy)</param>
        /// <param name="IobConfFull">Configurazione (v 4.x)</param>
        public OpcUaKpwRama(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo("Init OpcUa Kepware x RAMA");
            sendKeyRichiesta = true;
        }

        /// <summary>
        /// Effettua sync dati inviando RICETTA
        /// </summary>
        protected override void ProcessDataSync()
        {
            lgInfo("--------------------------------------------");
            lgInfo($"executeTasks --> syncDbData --> ProcessDataSync");
            lgInfo("--------------------------------------------");
            // effettua sync recuperando dati ed effettuando scrittura su kepware
            var taskGet = IobGetSendDossierKepware();

        }

        /// <summary>
        /// Recupero dati da server x invio dati ricetta a KepWare (Ex RAMA x TFT)
        /// </summary>
        /// <returns></returns>
        private bool IobGetSendDossierKepware()
        {
            bool answ;

            lgInfo("iobGetSendOdlDP: Inizio scrittura dati a KepWare");
            /*-----------------------------------------
             * STEPS processo:
             * - recupero ARTICOLI (solo quelli dei PODL attivi)
             * - recupero PODL (tutti)
             * - recupero elenco DOSSIER last x macchina (legato ai PODL attivi)
             * - prendo SOLO PODL attivi, e prendo il + vecchio
             * - se trovo dossier x articolo del PODL + vecchio (e dovrebbe...) procedo
             * - uso Dictionary dei memWrite x tradurre l'elenco fluxLog in nuovi valori
             * - preparo il set di valori da scrivere con traduzione
             * - invio scritture
             * - aggiungo info articolo (+ ODL...)
             * - aggiungo il valore di "scrittura effettuata"
             *----------------------------------------- */

            bool okArt = false;
            bool okDoss = false;
            bool okPodl = false;
            List<AnagArticoli> listaArt = new List<AnagArticoli>();
            List<PODLModel> listaPODL = new List<PODLModel>();
            List<DossiersModel> listaDoss = new List<DossiersModel>();
            // recupera dati da server tramite chiamate REST a MP/IO/IOB...
            try
            {
                // PONTE SYNC/ASYNC: Ora sw.Stop() aspetterà la fine reale dell'operazione
                Task.Run(async () =>
                {
                    var rawListArt = await callUrl(urlGetCurrArt, false);
                    var rawListDOSS = await callUrl(urlGetCurrDOSS, false);
                    // fixme todo verificare se usare urlGetActPODL
                    var rawListPODL = await callUrl(urlGetNextPODL, false);
                    if (!string.IsNullOrEmpty(rawListArt))
                    {
                        try
                        {
                            listaArt = JsonConvert.DeserializeObject<List<AnagArticoli>>(rawListArt);
                            okArt = listaArt.Count > 0;
                        }
                        catch (Exception exc)
                        {
                            lgError($"Errore: chiamata elenco ART ha restituito errore{Environment.NewLine}{exc}");
                        }
                    }
                    else
                    {
                        lgError($"Errore: chiamata elenco ART ({urlGetCurrArt}) ha restituito valore vuoto");
                    }
                    if (!string.IsNullOrEmpty(rawListDOSS))
                    {
                        try
                        {
                            listaDoss = JsonConvert.DeserializeObject<List<DossiersModel>>(rawListDOSS);
                            okDoss = listaDoss.Count > 0;
                        }
                        catch (Exception exc)
                        {
                            lgError($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
                        }
                    }
                    else
                    {
                        lgError($"Errore: chiamata elenco DOSSIER ({urlGetCurrDOSS}) ha restituito valore vuoto");
                    }
                    if (!string.IsNullOrEmpty(rawListPODL))
                    {
                        try
                        {
                            listaPODL = JsonConvert.DeserializeObject<List<PODLModel>>(rawListPODL);
                            okPodl = listaPODL.Count > 0;
                        }
                        catch (Exception exc)
                        {
                            lgError($"Errore: chiamata elenco DOSSIER ha restituito errore{Environment.NewLine}{exc}");
                        }
                    }
                    else
                    {
                        lgError($"Errore: chiamata elenco PODL ({urlGetNextPODL}) ha restituito valore vuoto");
                    }
                })
                .GetAwaiter()
                .GetResult();
            }
            catch (Exception ex)
            {
                lgError($"Errore in IobGetSendDossierKepware | {Environment.NewLine}{ex.Message}");
            }
            // continuo verifica
            answ = okArt && okPodl && okDoss;
            if (answ)
            {
                // verifico i PODL attivi...
                var listPodlAct = listaPODL.Where(x => x.Attivabile).OrderBy(x => x.InsertDate).ToList();
                if (listPodlAct.Count > 0)
                {
                    string codArt = listPodlAct.FirstOrDefault().CodArticolo;
                    // verifico di avere il dossier e l'articolo x questo PODL
                    var selArt = listaArt.Where(x => x.CodArticolo == codArt).FirstOrDefault();
                    var selDoss = listaDoss.Where(x => x.CodArticolo == codArt).FirstOrDefault();
                    // prendo il primo e recupero...
                    if (selArt != null && selDoss != null)
                    {
                        // recupero il resultset dei valori FluxLog da caricare
                        DossierFluxLogDTO resultSet = JsonConvert.DeserializeObject<DossierFluxLogDTO>(selDoss.Valore);
                        List<FluxLog> listFluxLog = resultSet.ODL;

                        // preparo elenco parametri da inviare...
                        list2Write = new List<objItem>();
                        // per ogni valore ricevuto nel dossier --> calcolo parametro da inviare
                        foreach (var item in listFluxLog)
                        {
                            objItem currData = new objItem()
                            {
                                uid = item.CodFlux,
                                reqValue = item.Valore,
                                name = item.CodFlux
                            };
                            // aggiungo!
                            list2Write.Add(currData);
                            lgInfo($"Add param: {currData.uid} | reqVal: {currData.reqValue}");
                        }
                        // aggiungo ultimo parametro di newRecipe...
                        objItem newRecipeData = new objItem()
                        {
                            uid = "NewRecipe",
                            reqValue = "true",
                            name = "NewRecipe"
                        };
                        list2Write.Add(newRecipeData);

                        // effettua chiamata scrittura verso impianto...
                        plcWriteParams(ref list2Write);
                    }
                }
            }
            return answ;
        }

     
        #endregion Public Constructors

    }
}