using System;
using System.Threading.Tasks;
using Quadarax.Foundation.Core.Logging;

namespace Quadarax.Foundation.Core.Thread
{
    public class LoopWorker : AbstractWorker
    {
        #region *** Private fields ***
        private TimeSpan _defaultTimeout;
        private long _cntLimit;
        #endregion

        #region *** Properties ***
        public long IterationsLimit { get; set; } = 0;
        public TimeSpan IterationsDelayBetween { get; set; } = TimeSpan.Zero;
        #endregion

        #region *** Constructors ***
        public LoopWorker(IWorkerContext context) : base(context)
        {

        }
        public LoopWorker(string workerName, IWorkerContext context) : base(workerName, context)
        {
        }
        public LoopWorker(string workerName) : base(workerName)
        {

        }
        public LoopWorker(string workerName, IWorkerContext context, ILogger logger = null) : base(workerName, context, logger)
        {
        }
        #endregion

        #region *** Public Operations ***
        #endregion

        #region *** Virtuals and protected ***

        protected override async Task Do(IWorkerContext context)
        {
            var exit = false;
            var first = true;
            while (!exit)
            {
                if (first)
                    first = false;
                else if (IterationsDelayBetween != TimeSpan.Zero)
                    System.Threading.Thread.CurrentThread.Join(IterationsDelayBetween);

                if (IterationsLimit == 0)
                {
                    await DoIteration(context);
                }
                else
                {
                    await DoIteration(context);
                    _cntLimit++;
                    if (_cntLimit > IterationsLimit)
                        exit = true;
                }
            }
        }
        protected virtual async Task DoIteration(IWorkerContext context)
        {
        }

        protected override void OnBeforeStart()
        {
            base.OnBeforeStart();
            _defaultTimeout = Timeout;
            Timeout = TimeSpan.Zero;
        }
        protected override void OnAfterStop()
        {
            base.OnAfterStop();
            Timeout = _defaultTimeout;
            _cntLimit = 0;
        }
        #endregion

        #region *** Private Operations ***
        #endregion

    }
}
