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

// ReSharper disable InconsistentNaming

namespace BO.ProcessServer.Business.StatisticCounters
{
    internal class Statistics
    {
        #region *** Constants ***
        public const string CNT_PS_ONLINE_DUR = "ProcessServerOnline";

        public const string CNT_SCENARIO_PROCESSED_INC = "ScenariosProcessedCount";
        public const string CNT_SCENARIO_PROCESSED_OK_INC = "ScenariosProcessedOkCount";
        public const string CNT_SCENARIO_PROCESSED_FAIL_INC = "ScenariosProcessedFailCount";

        public const string CNT_SCENARIO_AVG_DUR = "ScenariosAVGDuration";
        public const string CNT_SCENARIO_MIN_DUR = "ScenariosMINDuration";
        public const string CNT_SCENARIO_MAX_DUR = "ScenariosMAXDuration";
        #endregion

        #region *** Private fields ***
        private IList<BaseCounter> _counters = new List<BaseCounter>();
        #endregion

        #region *** Constructors ***
        public Statistics()
        {
            _counters.Add(new TimespanAVGCounter(CNT_SCENARIO_AVG_DUR));
            _counters.Add(new TimespanMINCounter(CNT_SCENARIO_MIN_DUR));
            _counters.Add(new TimespanMAXCounter(CNT_SCENARIO_MAX_DUR));
            _counters.Add(new IncrementalCounter(CNT_SCENARIO_PROCESSED_INC));
            _counters.Add(new IncrementalCounter(CNT_SCENARIO_PROCESSED_OK_INC));
            _counters.Add(new IncrementalCounter(CNT_SCENARIO_PROCESSED_FAIL_INC));
            _counters.Add(new TimespanCounter(CNT_PS_ONLINE_DUR));
        }
        #endregion

        #region *** Public Operations ***
        public BaseCounter GetCounter(string name)
        {
            CheckExistenceCounter(name);
            return _counters.First(x => x.Name == name);
        }
        public TCounter GetCounter<TCounter>(string name) where TCounter : BaseCounter
        {
            return (TCounter)GetCounter(name);
        }
        public void ResetCounter(string name)
        {
            CheckExistenceCounter(name);

        }
        public override string ToString()
        {
            return base.ToString();
        }

        #endregion

        #region *** Private Operations ***

        private bool ExistsCounter(string name)
        {
            return GetCounterInternal(name)!=null;
        }

        private BaseCounter GetCounterInternal(string name)
        {
            return _counters.FirstOrDefault(x => x.Name == name);
        }

        private void CheckExistenceCounter(string name)
        {
            if (!ExistsCounter(name))
                throw new ArgumentOutOfRangeException(nameof(name),$"Counter '{name}' doesn't exists!");
        }
        #endregion
    }
}
