using UnityEngine;
using System;
using System.Collections.Generic;

namespace mgaia.Utils
{
    /// <summary>
    /// Representa um agendamento (schedule)
    /// </summary>
    /// <owner>Victor</owner>
    internal class SchedulePayload
    {
        private uint mNumberOfTimesToCall;
        private uint mActualNumberOfCalls;
        private float mCurrentTime;
        private float mInterval;

        private Action _mAction;

        /// <summary>
        /// Retorna se o schedule é infinito
        /// </summary>
        private bool IsInfinity
        {
            get { return mNumberOfTimesToCall == Constants.INFINITY_NUMBER_OF_TIMES_TO_CALL; }
        }

        /// <summary>
        /// Retorna se é necessário remover o schedule
        /// </summary>
        internal bool NeedsToRemove
        {
            get;
            set;
        }

        /// <summary>
        /// Retorna se o schedule está pausado ou não
        /// </summary>
        internal bool Paused
        {
            get;
            set;
        }

        /// <summary>
        /// Retorna a ação chamada pelo schedule
        /// </summary>
        internal Action Action
        {
            get { return _mAction; }
        }

        public SchedulePayload(Action action, uint numberOfTimesToCall, float interval)
        {
            _mAction = action;
            mNumberOfTimesToCall = numberOfTimesToCall;

            if (IsInfinity)
            {
                mActualNumberOfCalls = mNumberOfTimesToCall;
            }

            mCurrentTime = 0;
            mInterval = interval;

            NeedsToRemove = false;
        }
        
		/// <summary>
		/// Reseta o contador do payload
		/// </summary>
		public void Reset()
		{
			mCurrentTime = 0;
		}

        /// <summary>
        /// Atualiza a timestamp do schedule
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public bool NeedsToCall(float time)
        {
            mCurrentTime += time;

            bool needsToCall = mCurrentTime.CompareTo(mInterval) >= 0;

            if (needsToCall)
            {
                mCurrentTime = 0;
            }

            return needsToCall;
        }

        /// <summary>
        /// Chama o método do schedule
        /// </summary>
        /// <returns></returns>
        public bool Invoke()
        {
            Assert.AssertTrue(IsInfinity || mActualNumberOfCalls < mNumberOfTimesToCall, "Esse schedule já foi chamado o número máximo de vezes!");

            _mAction();

            if (!IsInfinity)
            {
                mActualNumberOfCalls++;

                if (mActualNumberOfCalls == mNumberOfTimesToCall)
                {
                    return true;
                }
            }

            return false;
        }
    }
}