using EscapeRoomEngine.Engine.Runtime.Modules;
using NaughtyAttributes;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;

namespace EscapeRoomEngine.Desert.Runtime.Dispenser
{
    /// <summary>
    /// The main component for the dispenser module.
    /// </summary>
    [SelectionBase]
    [RequireComponent(typeof(Animator), typeof(Emission))]
    public class Dispenser : ModuleState
    {
        private static readonly int Open = Animator.StringToHash("Open");
        
        [Tooltip("The object this dispenser should produce.")]
        public Transform dispensable;
        [Tooltip("The time in seconds to wait until another object can be produced.")]
        [SerializeField] [Min(0)]
        private float cooldown;
        [BoxGroup("Internal")] [SerializeField]
        private Transform dispenseOrigin;
        [BoxGroup("Internal")] [SerializeField]
        private Button dispenseButton;

        /// <summary>
        /// The dispenser does not produce any more objects when it is solved and changes colour.
        /// </summary>
        public bool Solved
        {
            set
            {
                if (value)
                {
                    CloseHatch();
                    dispenseButton.Disable();
                    _light.color = Engine.Runtime.Engine.Theme.solvedColor.hdr;
                }
                else
                {
                    dispenseButton.Enable();
                    _light.color = Engine.Runtime.Engine.Theme.puzzleColor.hdr;
                }
            }
        }

        private float _previousDispense = -1;
        private Animator _animator;
        private Emission _light;

        private void Awake()
        {
            _animator = GetComponent<Animator>();
            _light = GetComponent<Emission>();
        }

        private void Start()
        {
            dispenseButton.ButtonEvent += (_, type) =>
            {
                if (type == ButtonEventType.Pressed)
                {
                    Dispense();
                }
            };

            _light.active = true;
        }

        #region Debug Buttons
        
        [Button(enabledMode: EButtonEnableMode.Playmode)]
        public void Dispense()
        {
            if (_previousDispense + cooldown <= Time.time)
            {
                Logger.Log($"{this} dispensing {dispensable.gameObject}", LogType.PuzzleDetail);

                _animator.SetBool(Open, true);
                Instantiate(dispensable, dispenseOrigin.position, dispenseOrigin.rotation);

                _previousDispense = Time.time;
            }
        }
        
        [Button(enabledMode: EButtonEnableMode.Playmode)]
        public void CloseHatch()
        {
            _animator.SetBool(Open, false);
        }

        [Button(enabledMode: EButtonEnableMode.Playmode)]
        public void Solve() => Solved = true;

        [Button(enabledMode: EButtonEnableMode.Playmode)]
        public void Reset() => Solved = false;

        #endregion

        public override void SetModule(Module module) {}
    }
}