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

using Svelto.Tasks.Lean;
using Svelto.Tasks.ExtraLean;

namespace GamecraftModdingAPI.Tasks
{
    /// <summary>
    /// Asynchronous task scheduling for ISchedulables.
    /// Asynchronous tasks will not freeze the main program, which makes them ideal for slow or blocking operations which don't need to be completed post-haste.
    /// The functionality of this class works in any state.
    /// </summary>
    public static class Scheduler
    {
        public static Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunnerUI
        {
            get
            {
                return RobocraftX.Schedulers.Lean.UIScheduler;
            }
        }

        public static Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunnerUI
        {
            get
            {
                return RobocraftX.Schedulers.ExtraLean.UIScheduler;
            }
        }

        public static readonly Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunner = new Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner("GamecraftModdingAPIExtraLean");

        public static readonly Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunner = new Svelto.Tasks.Lean.Unity.UpdateMonoRunner("GamecraftModdingAPILean");

        /// <summary>
        /// Schedule a task to run asynchronously.
        /// This uses custom task runners (by default) to not interfere with the game.
        /// </summary>
        /// <param name="toRun">The task to run</param>
        /// <param name="extraLean">Schedule toRun on an extra lean runner?</param>
        /// <param name="ui">Schedule toRun on Gamecraft's built-in UI task runner?</param>
        public static void Schedule(ISchedulable toRun, bool extraLean = false, bool ui = false)
        {
            if (extraLean)
            {
                if (ui)
                {
                    toRun.Run().RunOn(extraLeanRunnerUI);
                }
                else
                {
                    toRun.Run().RunOn(extraLeanRunner);
                }
                
            }
            else
            {
                if (ui)
                {
                    toRun.Run().RunOn(leanRunnerUI);
                }
                else
                {
                    toRun.Run().RunOn(leanRunner);
                }
            }
            
        }

        public static void Dispose()
        {
            leanRunner.Stop();
            extraLeanRunner.Stop();
            leanRunner.Dispose();
            extraLeanRunner.Dispose();
        }
    }
}