using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IOB_UT
{
    /// <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 Protected Properties

        /// <summary>
        /// Fattore lambda (innovazione) per calcolo EWMA valore TCiclo corrente
        /// </summary>
        protected double _lambda { get; set; } = 0.4;

        /// <summary>
        /// Ultimo TCiclo osservato in SECONDI
        /// </summary>
        protected double _lastTC { get; set; } = 0;

        /// <summary>
        /// ULTIMO Contapezzi IOB VALIDO
        /// </summary>
        protected int _lastValidPzCountIOB { get; set; } = 0;

        /// <summary>
        /// ULTIMO Contapezzi PLC VALIDO
        /// </summary>
        protected int _lastValidPzCountPLC { get; set; } = 0;

        /// <summary>
        /// Fattore massimo ammesso di delay x il TCiclo
        /// </summary>
        protected double _maxDelayFactor { get; set; } = 1.2;

        /// <summary>
        /// Incremento amssimo pezzi per cui fare calcolo del tempociclo attuale
        /// </summary>
        protected double _maxIncrPz { get; set; } = 2;

        /// <summary>
        /// Contapezzi IOB
        /// </summary>
        protected int _pzCountIOB { get; set; } = 0;

        /// <summary>
        /// Contapezzi PLC
        /// </summary>
        protected int _pzCountPLC { get; set; } = 0;

        #endregion Protected Properties

        #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);
                }
                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(-1);

        /// <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; set; } = 0;

        /// <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
    }
}