using IOB_UT_NEXT;
using NLog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using static IOB_UT_NEXT.BaseAlarmConf;

namespace IOB_WIN_FORM.Iob
{
    /// <summary>
    /// Classe di base per IOB
    /// </summary>
    public class BaseObj : IOB_UT_NEXT.Iob.BaseObj
    {
        #region Protected Fields

        /// <summary>
        /// Form chiamante
        /// </summary>
        protected AdapterForm parentForm;

        /// <summary>
        /// Num errori lettura correnti
        /// </summary>
        protected int readErrorCurr = 0;

        /// <summary>
        /// Max num errori lettura prima di disconnettere
        /// </summary>
        protected int readErrorMax = 10;

        /// <summary>
        /// </summary>
        protected int readErrorSleepTime = 15000;

        #endregion Protected Fields

        #region Protected Properties

        /// <summary>
        /// Wrapper di log
        /// </summary>
        protected virtual Logger lg
        {
            get => _logger;
        }

        #endregion Protected Properties

        #region Protected Methods

        /// <summary>
        /// Effettua logging DEBUG corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgDebug(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(20, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Debug(message);
                if (sendToForm)
                {
                    sendToLogWatch("DEBUG", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging DEBUG corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgDebug(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(20, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Debug(message, args);
                sendToLogWatch("DEBUG", message, args);
            }
        }

        /// <summary>
        /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgError(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(2, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Error(message, args);
                sendToLogWatch("ERROR", message, args);
            }
        }

        /// <summary>
        /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgError(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(2, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Error(message);
                if (sendToForm)
                {
                    sendToLogWatch("ERROR", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging ERROR corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgError(Exception exception, string message, params object[] args)
        {
            bool doVeto = checkLogVeto(2, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Error(exception, message, args);
                sendToLogWatch("ERROR", message, exception, args);
            }
        }

        /// <summary>
        /// Effettua logging FATAL corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgFatal(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(1, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Fatal(message);
                if (sendToForm)
                {
                    sendToLogWatch("FATAL", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging FATAL corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgFatal(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(1, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Fatal(message, args);
                sendToLogWatch("FATAL", message, args);
            }
        }

        /// <summary>
        /// Effettua logging FATAL corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgFatal(Exception exception, string message, params object[] args)
        {
            bool doVeto = checkLogVeto(1, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Fatal(exception, message, args);
                sendToLogWatch("FATAL", message, exception, args);
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgInfo(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(30, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Info(message);
                if (sendToForm)
                {
                    sendToLogWatch("INFO", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgInfo(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(30, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Info(message, args);
                sendToLogWatch("INFO", message, args);
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="sendToForm"></param>
        protected virtual void lgInfoStartup(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(30, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                DateTime adesso = DateTime.Now;
                if (adesso.Subtract(lastLogStartup).TotalMinutes > vetoLogStartupDuration)
                {
                    lg.Info(message);
                    // se supera di 5 minutis cadenza -_> reimposto veto...
                    if (adesso.Subtract(lastLogStartup).TotalMinutes > vetoLogStartupDuration + 5)
                    {
                        lastLogStartup = adesso;
                    }
                }
                if (sendToForm)
                {
                    sendToLogWatch("INFO", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgInfoStartup(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(30, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                DateTime adesso = DateTime.Now;
                if (adesso.Subtract(lastLogStartup).TotalMinutes > vetoLogStartupDuration)
                {
                    lg.Info(message, args);
                    // se supera di 5 minutis cadenza -_> reimposto veto...
                    if (adesso.Subtract(lastLogStartup).TotalMinutes > vetoLogStartupDuration + 5)
                    {
                        lastLogStartup = adesso;
                    }
                }
                sendToLogWatch("INFO", message, args);
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgTrace(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(60, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Trace(message);
                if (sendToForm)
                {
                    sendToLogWatch("TRACE", message);
                }
            }
        }

        /// <summary>
        /// Effettua logging INFO corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected virtual void lgTrace(string message, params object[] args)
        {
            bool doVeto = checkLogVeto(60, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Trace(message, args);
                sendToLogWatch("TRACE", message, args);
            }
        }

        /// <summary>
        /// Effettua logging WARN corretto impostanto anche la variabile IOB prima di scrivere...
        /// </summary>
        /// <param name="message"></param>
        protected virtual void lgWarn(string message, bool sendToForm = true)
        {
            bool doVeto = checkLogVeto(30, ref message);
            // se non ho veto --> loggo
            if (!doVeto)
            {
                lg.Factory.Configuration.Variables["codIOB"] = IOBConfFull.General.FilenameIOB;
                lg.Warn(message);
                if (sendToForm)
                {
                    sendToLogWatch("WARN", message);
                }
            }
        }

        /// <summary>
        /// Invia messaggio a logWatcher
        /// </summary>
        /// <param name="messType"></param>
        /// <param name="message"></param>
        protected void sendToLogWatch(string messType, string message)
        {
            newDisplayData currDispData = new newDisplayData();
            currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | {messType} | {message}";
            parentForm.updateFormDisplay(currDispData);
        }

        /// <summary>
        /// Invia messaggio a logWatcher
        /// </summary>
        /// <param name="messType"></param>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected void sendToLogWatch(string messType, string message, params object[] args)
        {
            try
            {
                string expString = string.Format(message, args);
                newDisplayData currDispData = new newDisplayData();
                currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | {messType} | {expString}";
                parentForm.updateFormDisplay(currDispData);
            }
            catch
            { }
        }

        /// <summary>
        /// Invia messaggio a logWatcher
        /// </summary>
        /// <param name="messType"></param>
        /// <param name="exception"></param>
        /// <param name="message"></param>
        /// <param name="args"></param>
        protected void sendToLogWatch(string messType, string message, Exception exception, params object[] args)
        {
            try
            {
                string expString = string.Format(message, args);
                newDisplayData currDispData = new newDisplayData();
                currDispData.newLiveLogData = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} | {messType} | {expString}{Environment.NewLine}{exception}";
                parentForm.updateFormDisplay(currDispData);
            }
            catch
            { }
        }

        #endregion Protected Methods

        #region Private Fields

        /// <summary>
        /// Oggetto logger della classe
        /// </summary>
        private static Logger _logger = LogManager.GetCurrentClassLogger();

        #endregion Private Fields
    }
}