using IOB_UT_NEXT;
using IOB_UT_NEXT.Config;
using System;
using System.Globalization;
using System.IO;

namespace IOB_WIN_MBUS.IobModbusTCP
{
    /* --------------------------------------------------------------------------------
    * Controlli ModBusTCP FIMAT
    * - protocollo ModBus TCP
    * - gestione stato via Modbus
    * - resto gestioen via file
    *
    * G:\Drive condivisi\30_Clienti\Tenditalia\Macchina Fimat
    *
    * -------------------------------------------------------------------------------- */

    public class ModbusTCPFimat : 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 ModbusTCPFimat(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
        {
            lgInfo("NEW IOB ModBus TCP FIMAT");

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

        #endregion Public Constructors

        #region Protected Fields

        /// <summary>
        /// Quantità massima PODL prima di fare split ordine (default 999'999)
        /// </summary>
        protected int maxPodlQty = 999999;

        #endregion Protected Fields

        #region Protected Properties

        /// <summary>
        /// Restituisce controllo IN ALLARME
        /// </summary>
        protected bool AlarmState
        {
            get
            {
                return testIntCondition("AlarmIntCond");
            }
        }

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

        /// <summary>
        /// Restituisce status di Manuale, hard coded
        /// </summary>
        protected bool ManualState
        {
            get
            {
                return testBitCondition("ManualBitCond");
            }
        }

        /// <summary>
        /// Restituisce status di WORK (auto + lavora), hard coded
        /// </summary>
        protected bool WorkState
        {
            get
            {
                return testIntCondition("WorkIntCond");
            }
        }

        #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);
            }
            // se ho qualcosa nella holding register...
            if (HoldingRegisterLUT != null && HoldingRegisterLUT.Count > 0)
            {
                // se emergenza NON premuta (triggered) indico OK (armata...) FARE !!! togliere true
                if (!EStopTriggered)
                {
                    byteSignals += (1 << 7);
                }

                // impiego controlli da setup IntConditions... processo dagli stati + gravi...
                if (AlarmState || hasAlarms())
                {
                    byteSignals += (1 << 3);
                }
                else if (ManualState)
                {
                    byteSignals += (1 << 4);
                }
                else if (WorkState)
                {
                    byteSignals += (1 << 1);
                }

                checkTranslateBit();
                checkTranslateInt();
            }
            else
            {
                lgInfo("HoldingRegisterLUT vuoto!");
            }

            // salvo!
            B_input = byteSignals;
        }

        /// <summary>
        /// Effettua sync dati x PODL attivi
        /// </summary>
        protected override void ProcessDataSync()
        {
            if (hasRecipe)
            {
                lgTrace("ProcessDataSync: START");
                DateTime adesso = DateTime.Now;
                Calendar cal = new CultureInfo("it-IT").Calendar;
                int week = cal.GetWeekOfYear(adesso, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
                string tempPath = Path.Combine(pathList["path-locBase"], pathList["path-01-Temp"]);
                string archPath = Path.Combine(pathList["path-locBase"], pathList["path-02-Sent"], $"{adesso:yyyy}", $"{week:00}");
                string remoPath = Path.Combine(pathList["path-locBase"], pathList["path-04-remReq"]);
                baseUtils.checkDir(tempPath);
                baseUtils.checkDir(archPath);
                try
                {
                    // recupero elenco PODL da processare, check PODL già inviati, save locale
                    bool create = RecipeReqWriteLocal(tempPath, useLocalRecipe);
                    // invio ricette a impianto
                    bool trasmitted = RecipeSend(tempPath, archPath, remoPath);
                }
                catch (Exception exc)
                {
                    lgError($"Eccezione in ProcessDataSync{Environment.NewLine}{exc}");
                }
                lgTrace("ProcessDataSync: Completed");
            }
            else
            {
                lgTrace("ProcessDataSync: NO exec, hasRecipe=false");
            }
        }

        #endregion Protected Methods
    }
}