using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using MapoSDK;
using Opc.Ua;
using System.Collections.Generic;
using System.Linq;

namespace IOB_WIN_OPC_UA.IobOpc
{
    public class OpcUaEwonAdige : OpcUaEwon
    {
        #region Public Constructors

        /// <summary>
        /// Estende l'init della classe base, impiegando il pacchetto Nuget OPC-UA foundation con la
        /// gestione specifica per EWON (es Adige/BLM, Stel) 
        /// 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 OpcUaEwonAdige(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo("Init Ewon versione Adige/BLM");
            sendKeyRichiesta = true;
        }

        #endregion Public Constructors

        #region Protected Methods

        /// <summary>
        /// Effettua vera scrittura parametri
        /// </summary>
        /// <param name="updatedPar"></param>
        protected override void plcWriteParams(ref List<objItem> updatedPar)
        {
            base.plcWriteParams(ref updatedPar);

            // se DEVO gestire setup Mecolpress...
            if (opcUaParams.SetupConf.SetupMode == IOB_UT_NEXT.MachineSetupMode.MECOLPRESS)
            {
                List<WriteValue> nodes2Write = new List<WriteValue>();
                // faccio un check tra i valori in memoria che devono corrispondere e se NON
                // corrispondono --> metto valore in scrittura...
                int numDiff = 0;
                foreach (var item in opcUaParams.SetupConf.checkParList)
                {
                    // cerco la memoria corrispondente...
                    var memorieMes = dataItemMem.Where(x => x.Key.Contains(item.Key)).ToList();
                    var memorieMac = dataItemMem.Where(x => x.Key.Contains(item.Value)).ToList();
                    // se ho trovato qualcosa verifico se corrispondono...
                    if (memorieMes.Count > 0 && memorieMes.Count > 0)
                    {
                        // controllo primo record con primo record
                        if (memorieMes.FirstOrDefault().Value.value != memorieMac.FirstOrDefault().Value.value)
                        {
                            numDiff++;
                        }
                    }
                }

                // ciclo le condizioni di uscita
                foreach (var item in opcUaParams.SetupConf.writeParAction)
                {
                    WriteValue commWriteVal = new WriteValue();
                    commWriteVal.NodeId = new NodeId(item.TargetParam);
                    commWriteVal.AttributeId = Attributes.Value;
                    commWriteVal.Value = new DataValue();
                    // se ho differenze --> scrivo richiesta attrezzaggio...
                    if (numDiff > 0)
                    {
                        commWriteVal.Value.Value = item.TargetValNotEqual;
                    }
                    else
                    {
                        commWriteVal.Value.Value = item.TargetValEqual;
                    }

                    // accodo x scrittura
                    nodes2Write.Add(commWriteVal);
                    lgInfo($"richiesta scrittura valore | nodeId: {commWriteVal.NodeId} | targetPar: {item.TargetParam} | val {commWriteVal.Value.Value}");

                }

                // x ora NON eseguo
                if (opcUaParams.SetupConf.EnableAdvSetup)
                {
                    // ora scrivo!
                    if (nodes2Write.Count > 0)
                    {
                        UA_ref.WriteNodes(nodes2Write);
                    }
                }
            }
        }

        #endregion Protected Methods



        /// <summary>
        /// Processing degli allarmi (se presenti e gestiti)
        /// </summary>
        /// <returns></returns>
        public override Dictionary<string, string> getAlarmData()
        {
            Dictionary<string, string> outVal = new Dictionary<string, string>();
            // ora aggiungo (se ci fossero) gli allarmi...
            if (alarmMaps != null && alarmMaps.Count > 0)
            {
                if (hasAlarms())
                {
                    string bankVal = "";
                    foreach (var item in alarmMaps)
                    {
                        bankVal = "";
                        var currState = currAlarmsState(item);
                        // calcolo vettore stringa degli allarmi...
                        bankVal = getAlarmState(item, currState);
                        bankVal = string.IsNullOrEmpty(bankVal) ? "OK" : bankVal;
                        saveAlarmString(ref outVal, bankVal, item.description);
                    }
                }
            }
            else
            {
                lgTrace("No alarm found in alarmMaps");
            }

            if (periodicLog || outVal.Count > 0)
            {
                lgDebug($"Esito getAlarmData: {outVal.Count} allarmi attivi/validi in outVal");
            }
            return outVal;
        }
    }
}