using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using NaughtyAttributes.Test;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Ktyl.Util
{
    [CreateAssetMenu(menuName = "ktyl/Events/Game Event")]
    public partial class GameEvent : ScriptableObject
    {
        [SerializeField] private bool _logRaised;

        protected readonly List<GameEventListener> _listeners = new List<GameEventListener>();

        private readonly List<GameEventListener> _listenerBuffer = new List<GameEventListener>();
        
        public virtual void Raise()
        {
            if (_logRaised)
            {
                Debug.Log($"raised {this}", this);
            }

            // populate a buffer of listeners, since the original list
            // may be modified as a consequence of triggering the event
            _listenerBuffer.Clear();
            _listenerBuffer.AddRange(_listeners);
            
            foreach (var listener in _listenerBuffer)
            {
                listener.OnEventRaised();
            }
        }

        public void Register(GameEventListener listener)
        {
            if (_listeners.Contains(listener))
            {
                Debug.LogError($"{listener} already registered", this);
                return;
            }
            
            _listeners.Add(listener);
        }

        public void Unregister(GameEventListener listener)
        {
            if (!_listeners.Contains(listener))
            {
                Debug.LogError($"{listener} not already registered");
                return;
            }

            _listeners.Remove(listener);
        }
    }
    
    #region Editor
    #if UNITY_EDITOR

    public partial class GameEvent
    {
        private int _EDITOR_pingIdx;
        
        public void EDITOR_PingNextListener()
        {
            Debug.Log($"ping listener {_EDITOR_pingIdx+1}/{_listeners.Count}", this);
            
            EditorGUIUtility.PingObject(_listeners[_EDITOR_pingIdx++]);
            _EDITOR_pingIdx %= _listeners.Count;
        }
    }
    
    [CustomEditor(typeof(GameEvent), true)]
    public class GameEventEditor : Editor
    {
        private GameEvent _event;

        private void OnEnable()
        {
            _event = target as GameEvent;
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            if (GUILayout.Button("Raise"))
            {
                _event.Raise();
            }

            if (Application.isPlaying && GUILayout.Button("Ping Listeners"))
            {
                _event.EDITOR_PingNextListener();
            }
        }
    }
    
    #endif  
    #endregion
}