﻿using System;
using JLGames.RocketDriver.Actions.Utils;
using JLGames.RocketDriver.CSharp;
using UnityEngine;
using Object = UnityEngine.Object;

namespace JLGames.RocketDriver.Actions.Wait
{
    public static class WaitBehaviourShared
    {
        private const string Name = "MonoWaitBehaviour";
        
        private static WaitBehaviour m_Shared;

        public static WaitBehaviour Shared
        {
            get
            {
                if (null != m_Shared) return m_Shared;

                m_Shared = CreateWaitBehaviourObject();
                return m_Shared;
            }
        }

        public static void DestoryShared()
        {
            if (null == m_Shared) return;

            TransformUtil.RemoveAndDestroy(m_Shared.gameObject);
            m_Shared = null;
        }

        public static void InvokdEndOfFrame(Callback call, int weight = 0)
        {
            Shared.InvokdEndOfFrame(call, weight);
        }

        public static void InvokdEndOfFrame(Action call, int weight = 0)
        {
            Shared.InvokdEndOfFrame(call, weight);
        }

        public static void InvokdEndOfFrame<T>(Action<T> call, T arg, int weight = 0)
        {
            Shared.InvokdEndOfFrame(call, arg, weight);
        }

        public static void InvokdFixedUpdate(Callback call, int weight = 0)
        {
            Shared.InvokdFixedUpdate(call, weight);
        }

        public static void InvokdFixedUpdate(Action call, int weight = 0)
        {
            Shared.InvokdFixedUpdate(call, weight);
        }

        public static void InvokdFixedUpdate<T>(Action<T> call, T arg, int weight = 0)
        {
            Shared.InvokdFixedUpdate(call, arg, weight);
        }

        public static void InvokdSeconds(Callback call, float second)
        {
            Shared.InvokdSeconds(call, second);
        }

        public static void InvokdSeconds(Action call, float second)
        {
            Shared.InvokdSeconds(call, second);
        }

        public static void InvokdSeconds<T>(Action<T> call, T arg, float second)
        {
            Shared.InvokdSeconds(call, arg, second);
        }

        public static void InvokdSecondsRealtime(Callback call, float second)
        {
            Shared.InvokdSecondsRealtime(call, second);
        }

        public static void InvokdSecondsRealtime(Action call, float second)
        {
            Shared.InvokdSecondsRealtime(call, second);
        }

        public static void InvokdSecondsRealtime<T>(Action<T> call, T arg, float second)
        {
            Shared.InvokdSecondsRealtime(call, arg, second);
        }

        public static void InvokdUntil(Callback call, Func<bool> predicate)
        {
            Shared.InvokdUntil(call, predicate);
        }

        public static void InvokdUntil(Action call, Func<bool> predicate)
        {
            Shared.InvokdUntil(call, predicate);
        }

        public static void InvokdUntil<T>(Action<T> call, T arg, Func<bool> predicate)
        {
            Shared.InvokdUntil(call, arg, predicate);
        }

        public static void InvokdWhile(Callback call, Func<bool> predicate)
        {
            Shared.InvokdWhile(call, predicate);
        }

        public static void InvokdWhile(Action call, Func<bool> predicate)
        {
            Shared.InvokdWhile(call, predicate);
        }

        public static void InvokdWhile<T>(Action<T> call, T arg, Func<bool> predicate)
        {
            Shared.InvokdWhile(call, arg, predicate);
        }

        private static WaitBehaviour CreateWaitBehaviourObject()
        {
            var monoObj = new GameObject(Name);
            var mono = monoObj.AddComponent<WaitBehaviour>();
            mono.name = Name;
            Object.DontDestroyOnLoad(monoObj);
            return mono;
        }
    }
}