using Optional;
using System;

namespace BoFilTest.Domain
{
    public class Ticker
    {
        private Option<DateTime> lastTime;
        private TimeSpan interval;
        private TimeSpan untilNext;

        public Ticker()
        {
            this.lastTime = Option.None<DateTime>();
            this.interval = TimeSpan.Zero;
        }

        public void Tick(Action<DateTime> what)
        {
            this.lastTime.MatchSome(last =>
            {
                var now = DateTime.Now;
                var delta = now - last;
                this.lastTime = Option.Some(now);

                if (this.interval.Equals(TimeSpan.Zero))
                {
                    what(now);
                    return;
                }

                this.untilNext = this.untilNext.Subtract(delta);
                if (this.untilNext <= TimeSpan.Zero)
                {
                    what(now);
                    this.untilNext = this.untilNext.Add(this.interval);
                }
            });
        }

        public void Start(TimeSpan interval)
        {
            this.interval = interval;
            var time = DateTime.Now;
            this.lastTime = Option.Some(time);
            this.untilNext = TimeSpan.Zero;
        }

        public void Stop()
        {
            this.lastTime = Option.None<DateTime>();
        }

        public void Reset()
        {
            this.untilNext = this.interval;
        }
    }
}
