using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using MapoSDK;
using Newtonsoft.Json;
using Opc.Ua;
using System;
using System.Collections.Generic;

namespace IOB_WIN_OPC_UA.IobOpc
{
    public class OpcUaEwonMonti : 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 Monti, Tenditalia)
        /// 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 OpcUaEwonMonti(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo("Init Ewon versione Monti (Tenditalia)");
            // impostazioni specifiche Ewon di Monti
            forceResetInRun = true;
            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)
        {
            dataConf currMem = null;
            int byteSize = 0;
            string memAddrWrite = "";
            string serObj = "";
            if (updatedPar != null)
            {
                List<WriteValue> nodes2Write = new List<WriteValue>();
                // controllo i parametri... ne gestisco 4...
                foreach (var item in updatedPar)
                {
                    try
                    {
                        memAddrWrite = "";
                        int valInt = 0;
                        double valReal = 0;
                        // cerco in area memMapWrite...
                        if (memMap.mMapWrite.ContainsKey(item.uid))
                        {
                            // recupero!
                            currMem = memMap.mMapWrite[item.uid];
                            byteSize = currMem.size;
                            memAddrWrite = currMem.memAddr;

                            WriteValue commWriteVal = new WriteValue();
                            commWriteVal.NodeId = new NodeId(currMem.memAddr);
                            commWriteVal.AttributeId = Attributes.Value;
                            commWriteVal.Value = new DataValue();
                            commWriteVal.Value.Value = item.reqValue;

                            // faccio preliminarmente upsertKey...
                            upsertKey(currMem.name, currMem.value);
                            serObj = JsonConvert.SerializeObject(item);
                            lgInfo($"Inizio processing plcWriteParams per {currMem.name} | valore richiesto {currMem.value}");
                            lgInfo($"---------------{Environment.NewLine}UPDATED PARAM:{Environment.NewLine}{serObj}{Environment.NewLine}---------------");
                            serObj = JsonConvert.SerializeObject(currMem);
                            lgInfo($"---------------{Environment.NewLine}MEMORY CONTENT:{Environment.NewLine}{serObj}{Environment.NewLine}---------------");

                            switch (currMem.tipoMem)
                            {
                                case plcDataType.Boolean:
                                    break;

                                case plcDataType.Int:
                                case plcDataType.DInt:
                                case plcDataType.Word:
                                case plcDataType.DWord:
                                    int.TryParse(item.reqValue, out valInt);
                                    commWriteVal.Value.Value = valInt;
                                    memAddrWrite = currMem.memAddr;
                                    break;

                                case plcDataType.Real:
                                    double.TryParse(item.reqValue, out valReal);
                                    commWriteVal.Value.Value = valReal;
                                    break;

                                case plcDataType.String:

                                    // verifico caso speciale: se è art/comm scrivo AFFIANCATE...
                                    if (item.uid == "setArt" | item.uid == "setComm")
                                    {
                                        // accodo commessa + articolo con padding secondo lunghezza...
                                        string codArt = "";
                                        if (currProdData.ContainsKey("setArt"))
                                        {
                                            codArt = string.IsNullOrEmpty(currProdData["setArt"]) ? "" : currProdData["setArt"];
                                        }
                                        string codComm = "";
                                        if (currProdData.ContainsKey("setComm"))
                                        {
                                            codComm = string.IsNullOrEmpty(currProdData["setComm"]) ? "" : currProdData["setComm"];
                                        }
                                        // padding...
                                        codArt = codArt.PadRight(20, ' ');
                                        codComm = codComm.PadRight(20, ' ');
                                        commWriteVal.Value.Value = $"{codComm}{codArt}";
                                    }
                                    break;

                                default:
                                    break;
                            }
                            lgInfo($"---------------{Environment.NewLine}OPC-UA data:{Environment.NewLine}NodeId: {commWriteVal.NodeId}{Environment.NewLine}Value: {commWriteVal.Value.Value}{Environment.NewLine}---------------");

                            if (!string.IsNullOrEmpty(memAddrWrite))
                            {
                                nodes2Write.Add(commWriteVal);
                                // 2023.09.19 resetto richiesta
                                item.reqValue = "";
                            }
                            else
                            {
                                lgInfo($"Errore: memAddrWrite vuoto!");
                            }
                        }
                        else
                        {
                            lgInfo($"Errore uid non trovato in area write memory: {item.uid}, ci sono {memMap.mMapWrite.Count} in area write");
                        }
                    }
                    catch (Exception exc)
                    {
                        lgError($"Eccezione in fase di plcWriteParams per item {item.uid} con valore {item.value}{Environment.NewLine}{exc}");
                    }
                }

                if (nodes2Write.Count > 0)
                {
                    UA_ref.WriteNodes(nodes2Write);
                }
            }
        }

        #endregion Protected Methods
    }
}