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

using Svelto.Tasks;
using Svelto.Tasks.Enumerators;

namespace GamecraftModdingAPI.Tasks
{
    /// <summary>
    /// An asynchronous repeating task.
    /// Once constructed, this can be run by scheduling it with Scheduler.Schedule()
    /// </summary>
    public class Repeatable : ISchedulable
    {
        /// <summary>
        /// Determines if the task should continue to repeat
        /// </summary>
        /// <returns>Whether the task should run again (true) or end (false)</returns>
        public delegate bool ShouldContinue();

        private ShouldContinue shouldContinue;

        private Action task;

        private float delay;

        public IEnumerator<TaskContract> Run()
        {
            while (shouldContinue())
            {
                task();
                yield return new WaitForSecondsEnumerator(delay).Continue();
            }
            yield return Yield.It;
        }

        /// <summary>
        /// Construct a repeating task
        /// </summary>
        /// <param name="task">The task to repeat</param>
        /// <param name="shouldContinue">The check to determine if the task should run again</param>
        /// <param name="delay">The time to wait between repeats (in seconds)</param>
        public Repeatable(Action task, ShouldContinue shouldContinue, float delay = 0.0f)
        {
            this.task = task;
            this.shouldContinue = shouldContinue;
            this.delay = delay;
        }

        /// <summary>
        /// Construct a repeating task
        /// </summary>
        /// <param name="task">The task to repeat</param>
        /// <param name="count">The amount of times to repeat</param>
        /// <param name="delay">The time to wait between repeats (in seconds)</param>
        public Repeatable(Action task, int count, float delay = 0.0f)
        {
            this.task = task;
            this.shouldContinue = () => { return count-- != 0; };
            this.delay = delay;
        }
    }
}