using EasyModbus;
using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using System;

namespace IOB_WIN_MBUS.IobModbusTCP
{
    /* --------------------------------------------------------------------------------
    * Controlli ModBusTCP IMAS Aeromeccanica
    * - protocollo ModBus TCP
    * - specifico comportamento impianti filtrazione IMAS Aeromeccanica
    * - gestione allarmi
    *
    * STRUTTURA MEMORIA a banchi di UInt16, convertiti successivamente in int EVENTUALMENTE divisi per 10/100/1000
    * G:\Drive condivisi\30_Clienti\Jetco\Manuali CNC-PLC\Aspiratori
    *
    * -------------------------------------------------------------------------------- */

    public class ModbusTCPImaxAeromec : ModbusTCP
    {
        #region Public Constructors

        /// <summary>
        /// Classe base con i metodi x ModBusTCP
        /// </summary>
        /// <param name="caller">Form chiamante</param>
        /// <param name="IOBConf">Configurazione (legacy)</param>
        /// <param name="IobConfFull">Configurazione (v 4.x)</param>
        public ModbusTCPImaxAeromec(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo("NEW IOB ModBus TCP IMAS Aeromec");

            // provo lettura una prima volta i dati DYN
            if (currPLC != null && currPLC.Connected)
            {
                try
                {
                    processDynData();
                }
                catch (Exception exc)
                {
                    lgError($"Eccezione in processDynData iniziale x ModBus TCP IMAS Aeromec:{Environment.NewLine}{exc}");
                }
            }
        }

        #endregion Public Constructors

        #region Protected Properties

        /// <summary>
        /// Restituisce status di AUTOmatico, hard coded
        /// </summary>
        protected bool Auto
        {
            get
            {
                return testCondition("WorkBitCond");
#if false
                bool answ = false;
                int currStatus = 0;
                // hard coded
                int statusReg = 40002;
                int[] listInt = new int[2];
                listInt = HoldingRegisterLUT[statusReg];
                currStatus = ModbusClient.ConvertRegistersToInt(listInt);
                // hard coded il 5° bit
                answ = ((currStatus & (1 << 14)) > 0);
                return answ;
#endif
            }
        }

        /// <summary>
        /// Restituisce status di ESTOP triggered (triggered = premuta, altrimenti armed)
        /// </summary>
        protected bool EStopTriggered
        {
            get
            {
                return testCondition("EStopBitCond");
            }
        }

        /// <summary>
        /// Restituisce status di LAVORA, hard coded
        /// </summary>
        protected bool Work
        {
            get
            {
                return testCondition("WorkBitCond");
#if false

                bool answ = false;
                int currStatus = 0;
                // hard coded
                int statusReg = 40002;
                int[] listInt = new int[2];
                listInt = HoldingRegisterLUT[statusReg];
                currStatus = ModbusClient.ConvertRegistersToInt(listInt);
                // hard coded il 5° bit
                answ = ((currStatus & (1 << 0)) > 0);
                return answ;
#endif
            }
        }

        #endregion Protected Properties

        #region Protected Methods

        /// <summary>
        /// Effettua decodifica aree memoria alla bitmap usata x MAPO
        /// </summary>
        protected override void decodeToBaseBitmap()
        {
            // init a zero...
            B_input = 0;

            /* -----------------------------------------------------
             * bitmap MAPO STANDARD 60
             * B0: POWER_ON
             * B1: RUN
             * B2: pzCount
             * B3: allarme
             * B4: manuale
             * B5: slowTC
             * B6: WarmUpCoolDown
             * B7: EmergArmata
             *
             ----------------------------------------------------- */

            var MemInt = new byte[2];

            int byteSignals = 0;
            // bit 0 (poweron) imposto a 1 SE connected...
            if (currPLC.Connected)
            {
                byteSignals += (1 << 0);
            }
            if (HoldingRegisterLUT != null && HoldingRegisterLUT.Count > 0)
            {
                // se emergenza NON premuta (triggered) indico OK (armata...)
                if (!EStopTriggered)
                {
                    byteSignals += (1 << 7);
                }

                // processo dagli stati + gravi...
                if (hasAlarms())
                {
                    byteSignals += (1 << 3);
                }
                if (Work)
                {
                    byteSignals += (1 << 1);
                }
                if (!Auto)
                {
                    byteSignals += (1 << 4);
                }
            }
            else
            {
                lgInfo("HoldingRegisterLUT vuoto!");
            }

            // salvo!
            B_input = byteSignals;
        }

        #endregion Protected Methods

        #region Private Methods

        /// <summary>
        /// Testa la condition modbus da LUT + configurazione
        /// </summary>
        /// <param name="cKey"></param>
        /// <returns></returns>
        private bool testCondition(string cKey)
        {
            bool answ = false;
            if (OptCheckCondBit.ContainsKey(cKey))
            {
                int currStatus = 0;
                int[] listInt = new int[2];
                listInt = HoldingRegisterLUT[OptCheckCondBit[cKey].BaseAddr];
                currStatus = ModbusClient.ConvertRegistersToInt(listInt);
                // hard coded il 9° bit a zero
                answ = ((currStatus & (1 << OptCheckCondBit[cKey].BitNum)) == OptCheckCondBit[cKey].ValOk);
                lgTrace($"testCondition for {cKey} | BaseAddr: {OptCheckCondBit[cKey].BaseAddr} | BitNum: {OptCheckCondBit[cKey].BitNum} | ValOk: {OptCheckCondBit[cKey].ValOk}");
            }
            else
            {
                lgTrace($"testCondition error: {cKey} not found");
            }
            return answ;
        }

        #endregion Private Methods
    }
}