using KBCore.Refs;
using NEG.UI.UnityUi.Buttons.Reaction;
using NEG.UI.UnityUi.Buttons.Settings;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace NEG.UI.UnityUi.Buttons
{
    [DefaultExecutionOrder(-1)]
    [RequireComponent(typeof(Button))]
    public class BaseButton : MonoBehaviour, ISelectHandler, IDeselectHandler, IPointerEnterHandler, IPointerExitHandler
    {
        public delegate void SelectionHandler(bool isSilent);
        /// 
        /// is silent
        /// 
        public event SelectionHandler OnSelected;
        public event SelectionHandler OnDeselected;
        public event Action OnButtonPressed;
        public bool Interactable { get => button.interactable; set => button.interactable = value; }
        public TMP_Text Text => text;
        [SerializeField, Self(Flag.Optional)] private Button button;
        [SerializeField, Child(Flag.Optional)] private TMP_Text text;
        [SerializeField, Child(Flag.Optional)] private Image icon;
        [SerializeField] private ButtonSettings groupButtonSettings;
        private readonly Dictionary behaviours = new Dictionary();
        public virtual void OnSelect(BaseEventData eventData) => OnSelected?.Invoke(eventData is SilentEventData);
        
        public void OnDeselect(BaseEventData eventData) => OnDeselected?.Invoke(eventData is SilentEventData);
        public void OnPointerEnter(PointerEventData eventData) => EventSystem.current.SetSelectedGameObject(gameObject);
        public void OnPointerExit(PointerEventData eventData)
        {
            if(EventSystem.current.currentSelectedGameObject == gameObject)
                EventSystem.current.SetSelectedGameObject(null);
        }
        public void SetText(string txt)
        {
            if(text == null)
                return;
            text.text = txt;
        }
        public void AddOrOverrideSetting(SettingData data)
        {
            if (behaviours.TryGetValue(data.Key, out var setting))
            {
                setting.ChangeData(data);
                return;
            }
            behaviours.Add(data.Key, MonoUiManager.Instance.BehavioursFactory.CreateInstance(data.Key, this, data));
        }
        public void RemoveSetting(string key)
        {
            if (!behaviours.TryGetValue(key, out var setting))
            {
                Debug.LogError($"Behaviour with key {key} was not found");
                return;
            }
            setting.Dispose();
            behaviours.Remove(key);
        }
        protected virtual void Awake()
        {
            button.onClick.AddListener(OnClicked);
            if (groupButtonSettings == null)
                MonoUiManager.Instance.DefaultUiSettings.Apply(this);
            else
                groupButtonSettings.Apply(this);
        }
        private void Start() => OnDeselect(null);
        private void OnValidate() => this.ValidateRefs();
        protected virtual void OnClicked()
        {
            OnDeselect(null);
            OnButtonPressed?.Invoke();
        }
    }
}