using System.Text;
using RebootKit.Engine.Foundation;
using RebootKit.Engine.Input;
using RebootKit.Engine.Main;
using UnityEngine;
using UnityEngine.InputSystem;
using Logger = RebootKit.Engine.Foundation.Logger;

namespace RebootKit.Engine.ConsoleUI {
    public class ConsoleUIService : ServiceMonoBehaviour {
        static readonly Logger s_Logger = new Logger(nameof(ConsoleUIService));

        [SerializeField] ConsoleVC m_ConsoleVC;
        [SerializeField] ScriptableInputAction m_ToggleAction;
        
        InputState m_InputState;

        readonly StringBuilder m_Content = new StringBuilder();

        public bool IsVisible => m_ConsoleVC.gameObject.activeSelf;

        void Awake() {
            m_InputState = RR.Input.NewInputState("ConsoleUI");
            m_InputState.Priority = int.MaxValue;
            m_InputState.LockCursor = false;
            m_InputState.HideCursor = false;
            m_InputState.IsActive = IsVisible;
            
            SetVisibility(false);
        }

        void OnDestroy() {
            m_InputState?.Dispose();
            m_InputState = null;
        }

        void OnEnable() {
            s_Logger.Info("OnEnable console");

            m_ToggleAction.Action.Enable();
            m_ToggleAction.Action.performed += OnToggleAction;

            m_ConsoleVC.InputSubmitted += OnUserInput;
            m_ConsoleVC.ClearRequested += Clear;
            RR.Console.OnOutputMessage += Write;
        }

        void OnDisable() {
            m_ToggleAction.Action.performed -= OnToggleAction;

            m_ConsoleVC.InputSubmitted -= OnUserInput;
            m_ConsoleVC.ClearRequested -= Clear;
            RR.Console.OnOutputMessage -= Write;
        }

        public override void Dispose() {
        }

        public void ToggleVisibility() {
            SetVisibility(!IsVisible);

            if (IsVisible) {
                m_ConsoleVC.SetMessageContent(m_Content.ToString());
            }
        }

        void OnUserInput(string input) {
            RR.Console.WriteToOutput("> " + input);
            RR.Console.Execute(input);
        }

        public void SetVisibility(bool visible) {
            m_ConsoleVC.gameObject.SetActive(visible);
            m_InputState.IsActive = visible;
        }

        public void Write(string message) {
            m_Content.AppendLine(message);
            m_ConsoleVC.SetMessageContent(m_Content.ToString());
        }

        public void Clear() {
            m_Content.Clear();
            m_ConsoleVC.SetMessageContent(string.Empty);
        }

        void OnToggleAction(InputAction.CallbackContext obj) {
            ToggleVisibility();
        }
    }
}