using System;
using System.Collections.Generic;

namespace BingoBrain.Core
{
    public class Gsss
    {
        public Action onFinish;
        private List<TaskProcedure> taskList;
        private bool isCancel = false;

        public int Count => taskList.Count;

        public Gsss()
        {
            taskList = new List<TaskProcedure>();
        }

        public Gsss(Action onFinish)
        {
            taskList = new List<TaskProcedure>();
            this.onFinish = onFinish;
        }

        public Gsss Add(Action<TaskProcedure> taskFunc)
        {
            TaskProcedure task = new TaskProcedure();
            task.Gsss = this;
            task.onTaskFunc = taskFunc;
            taskList.Add(task);
            return this;
        }

        public Gsss Add(bool result, Action<TaskProcedure> trueTaskFunc)
        {
            if (!result) return this;
            return Add(trueTaskFunc);
        }

        public Gsss Add(bool result, Action<TaskProcedure> trueTaskFunc, Action<TaskProcedure> falseTaskFunc)
        {
            if (result)
            {
                return Add(trueTaskFunc);
            }
            else
            {
                return Add(falseTaskFunc);
            }
        }

        public Gsss Add(float delayTime, Action<TaskProcedure> taskFunc)
        {
            TaskProcedure task = new TaskProcedure();
            task.Gsss = this;
            task.onTaskFunc = (taskParam) => { TimerHelper.mEasy.AddTimer(delayTime, () => { taskFunc(task); }); };
            taskList.Add(task);
            return this;
        }

        public Gsss AddDelay(float delayTime)
        {
            TaskProcedure task = new TaskProcedure();
            task.Gsss = this;
            task.onTaskFunc = (taskParam) =>
            {
                TimerHelper.mEasy.AddTimer(delayTime, () =>
                {
                    if (task.onComplete != null)
                    {
                        task.onComplete();
                    }
                });
            };
            taskList.Add(task);
            return this;
        }

        public Gsss Run(float delayTime)
        {
            TimerHelper.mEasy.AddTimer(delayTime, () => Run());
            return this;
        }

        public Gsss Run()
        {
            if (isCancel)
                return null;
            for (int i = 0; i < taskList.Count - 1; i++)
            {
                int index = i;
                int nextIndex = index + 1;
                taskList[index].onComplete = () => taskList[nextIndex].onTaskFunc(taskList[nextIndex]);
            }

            if (taskList.Count > 0)
            {
                taskList[taskList.Count - 1].onComplete = onFinish;
                taskList[0].onTaskFunc(taskList[0]);
            }

            return this;
        }

        public Gsss Clear()
        {
            onFinish = null;
            foreach (TaskProcedure task in taskList)
            {
                task.Dispose();
            }

            taskList.Clear();
            return this;
        }

        public Gsss Cancel()
        {
            isCancel = true;
            Clear();
            return this;
        }
    }


    public class TaskProcedure
    {
        public Gsss Gsss;
        public Action<TaskProcedure> onTaskFunc;
        public Action onComplete;

        public void InvokeComplete()
        {
            if (onComplete != null)
            {
                onComplete();
            }
        }

        public void DelayInvokeComplete(float delayTime)
        {
            TimerHelper.mEasy.AddTimer(delayTime, InvokeComplete);
        }

        public void Dispose()
        {
            Gsss = null;
            onTaskFunc = null;
            onComplete = null;
        }
    }
}