using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UIElements;
using PlayerInputManager = VOID.Generic.Player.Input.PlayerInputManager;

namespace VOID.UserInterface.Game
{
    public class ContextMenuUI : MonoBehaviour
    {
        public static ContextMenuUI current {get; private set;}

        // Visual Elements
        private VisualElement _optionsElement;
        private readonly List<Button> _options = new();

        private event Action BeforeClick;

        private void Awake()
        {
            current = this;
            
            var uiDocument = gameObject.GetComponent<UIDocument>();
            var templateElement = uiDocument.rootVisualElement;

            _optionsElement = templateElement.Q("options");
            _optionsElement.RegisterCallback<MouseLeaveEvent>(_ => PlayerInputManager.current.OnDefaultUse += Close);
            _optionsElement.RegisterCallback<MouseEnterEvent>(_ => PlayerInputManager.current.OnDefaultUse -= Close);
        }

        public void Start()
        {
            Close();
        }

        public void Prepare()
        {
            Close();
            
            PlayerInputManager.current.OnDefaultUse += Close;
            PlayerInputManager.current.OnContextUse += Close;

            var clickedPosition = RuntimePanelUtils.ScreenToPanel(_optionsElement.panel, Mouse.current.position.ReadValue());
            _optionsElement.style.bottom = new StyleLength(clickedPosition.y);
            _optionsElement.style.left = new StyleLength(clickedPosition.x);
        }

        public void AddBeforeClick(Action action)
        {
            BeforeClick += action;
        }

        public void AddOption(string text, Action action)
        {
            var option = new Button();
            option.AddToClassList("option");
            option.text = text;
            option.clicked += () => BeforeClick?.Invoke();
            option.clicked += Close;
            option.clicked += () => action?.Invoke();

            _optionsElement.Add(option);
            _options.Add(option);
        }

        public void Open()
        {
            if (_options.Count == 0) return;
            
            _optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.Flex);
        }

        public void Close()
        {
            BeforeClick = default;
            PlayerInputManager.current.OnDefaultUse -= Close;
            PlayerInputManager.current.OnContextUse -= Close;
            _optionsElement.style.display = new StyleEnum<DisplayStyle>(DisplayStyle.None);

            _optionsElement.Clear();
            _options.Clear();
        }
    }
}
