using System;
using System.Collections.Generic;
using System.Linq;
using RebootKit.Engine.Foundation;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.InputSystem;
using Logger = RebootKit.Engine.Foundation.Logger;

namespace RebootKit.Engine.Input {
    public class InputState {
        public string Name { get; private set; }
        public bool HideCursor { get; private set; }
        public bool LockCursor { get; private set; }

        public InputState(string name, bool hideCursor = false, bool lockCursor = false) {
            Name = name;
            HideCursor = hideCursor;
            LockCursor = lockCursor;
        }
    }
    
    public class InputService : IService {
        static readonly Logger s_Logger = new Logger(nameof(InputService));
        
        readonly Config m_Config;

        InputActionAsset m_InputActionAsset;

        List<InputState> m_States = new List<InputState>(16);

        public InputService(Config config) {
            m_Config = config;

            m_InputActionAsset = config.inputActionAsset;
        }

        public void Dispose() {
            m_InputActionAsset = null;
        }
 
        public void AddState(InputState state) {
            Assert.IsFalse(m_States.Contains(state), "State already exists in the input service.");
            Assert.IsNotNull(state, "Input state cannot be null.");
            Assert.IsNull(m_States.FirstOrDefault(t => t.Name.Equals(state.Name, StringComparison.Ordinal)), 
                          $"State with name '{state.Name}' already exists in the input service.");

            m_States.Add(state);
        }

        public void EnableControls() {
            m_InputActionAsset.Enable();
        }

        public void DisableControls() {
            m_InputActionAsset.Disable();
        }

        public bool AreControlsEnabled() {
            return m_InputActionAsset.enabled;
        }

        public InputAction FindInputAction(string path) {
            return m_InputActionAsset.FindAction(path);
        }

        public void LockCursor() {
            Cursor.lockState = CursorLockMode.Locked;
            Cursor.visible = false;
        }

        public void UnlockCursor() {
            Cursor.lockState = CursorLockMode.None;
            Cursor.visible = true;
        }

        [Serializable]
        public class Config {
            public InputActionAsset inputActionAsset;
        }
    }
}