using System;

namespace IOB_UT_NEXT
{
    /// <summary>
    /// TCiclo management class
    /// </summary>
    public class TCMan
    {
        #region Public Constructors

        /// <summary>
        /// Classe gestione TCiclo
        /// </summary>
        /// <param name="lambda">Fattore lambda x EWMA smooth</param>
        /// <param name="maxDelayFactor">Massimo fattore ritardo TC x errore</param>
        /// <param name="maxIncrPz">Massimo incremento numPz x considerare calcolo TCiclo</param>
        public TCMan(double lambda, double maxDelayFactor, double maxIncrPz)
        {
            _lambda = lambda;
            _maxDelayFactor = maxDelayFactor;
            _maxIncrPz = maxIncrPz;
        }

        #endregion Public Constructors

        #region Public Properties

        /// <summary>
        /// Indica se sia attivo allarme per TCiclo sopra soglia
        /// </summary>
        public bool alarmDelayTC
        {
            get
            {
                bool answ = false;
                // solo se ho dei pezzi rilevati...
                if (pzCountPLC > 0 && pzCountIOB > 0)
                {
                    answ = (currTC >= limitTC && limitTC > 0);
                }
                return answ;
            }
        }

        /// <summary>
        /// Valore TCiclo medio attuale (EWMA) in secondi
        /// </summary>
        public double avgTC { get; set; } = 0;

        /// <summary>
        /// TCiclo corrente
        /// </summary>
        public double currTC
        {
            get
            {
                DateTime adesso = DateTime.Now;
                return adesso.Subtract(lastObservedData).TotalSeconds;
            }
        }

        /// <summary>
        /// Ultimo dato (incremento PzCount) registrato
        /// </summary>
        public DateTime lastObservedData { get; set; } = DateTime.Now.AddMinutes(-60);

        /// <summary>
        /// Ultimo TCiclo osservato in secondi
        /// </summary>
        public double lastTC
        {
            get
            {
                return _lastTC;
            }
        }

        /// <summary>
        /// Limite allarme per il TCiclo (come media TCiclo * maxDelayFactor)
        /// </summary>
        /// <returns></returns>
        public double limitTC
        {
            get
            {
                return avgTC * _maxDelayFactor;
            }
        }

        /// <summary>
        /// Contapezzi IOB
        /// </summary>
        public int pzCountIOB
        {
            get => _pzCountIOB;
            set => _pzCountIOB = value;
        }

        /// <summary>
        /// Contapezzi PLC
        /// </summary>
        public int pzCountPLC
        {
            get
            {
                return _pzCountPLC;
            }
            set
            {
                DateTime adesso = DateTime.Now;
                int incrPz = value - _pzCountPLC;
                if (incrPz > 0)
                {
                    // calcolo lastTC...
                    _lastTC = adesso.Subtract(lastObservedData).TotalSeconds / incrPz;
                    // eseguo verifica x ricalcolo soglie...
                    bool validData = (incrPz) < _maxIncrPz;
                    if (validData)
                    {
                        avgTC = _lambda * lastTC + (1 - _lambda) * avgTC;
                    }
                }
                _pzCountPLC = value;
                // aggiorno dato osservazione...
                lastObservedData = adesso;
            }
        }

        #endregion Public Properties

        #region Private Fields

        /// <summary>
        /// Fattore lambda (innovazione) per calcolo EWMA valore TCiclo corrente
        /// </summary>
        private double _lambda = 0.4;

        /// <summary>
        /// Ultimo TCiclo osservato in SECONDI
        /// </summary>
        private double _lastTC = 0;

        /// <summary>
        /// Fattore massimo ammesso di delay x il TCiclo
        /// </summary>
        private double _maxDelayFactor = 1.2;

        /// <summary>
        /// Incremento amssimo pezzi per cui fare calcolo del tempociclo attuale
        /// </summary>
        private double _maxIncrPz = 2;

        /// <summary>
        /// Contapezzi IOB
        /// </summary>
        private int _pzCountIOB = 0;

        /// <summary>
        /// Contapezzi PLC
        /// </summary>
        private int _pzCountPLC = 0;

        #endregion Private Fields
    }
}