using System;
using System.Collections.Generic;
using Intrepid.Core.Entities;
using Intrepid.Core.Tags;
using Intrepid.GameManagers;
using Intrepid.Gameplay.Entities.Player.ActionBelt.Events;
using Intrepid.Gameplay.Entities.Player.Tags;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Intrepid.Gameplay.Entities.Player.ActionBelt
{
    public class ActionBeltTrigger : EntityTrigger
    {
        [GroupConfigurations, SerializeField, PropertySpace, PropertyOrder(12)] private List<ActionCallable> callables;

        protected override void WhenRaiseEnterEvent(Collider other, EntitySensor entitySensor, List<BehaviourTag> behaviourTags)
        {
            if (entitySensor.EntityTag is PlayerTag playerTag)
            {
                foreach (var callable in callables)
                {
                    if (callable.IsNull()) continue;
                    if (callable.IsNotEnabled) continue;
                    Proxy.Instance.EventBus.Raise(new ActionBeltAddEvent
                    {
                        ActionBeltManger = playerTag.ActionBeltManger,
                        ActionEnvelope = callable.BuildEnvelope(), 
                    });
                }
            }
        }

        protected override void WhenRaiseExitEvent(Collider other, EntitySensor entitySensor)
        {
            if (entitySensor.EntityTag is PlayerTag playerTag)
            {
                foreach (var callable in callables)
                {
                    Proxy.Instance.EventBus.Raise(new ActionBeltRemoveByIdEvent
                    {
                        ActionBeltManger = playerTag.ActionBeltManger,
                        ActionId = callable.Id,
                    });
                }
            }
        }
        
#if UNITY_EDITOR
        private static readonly Color CallableConnectionColor = new(1f, 0.72f, 0.12f, 1f);
        private static readonly Color CallableConnectionShadowColor = new(0f, 0f, 0f, 0.35f);

        private void OnDrawGizmosSelected()
        {
            DrawCallableConnections();
        }

        private void DrawCallableConnections()
        {
            if (callables == null || callables.Count == 0) return;

            var from = GetGizmoOrigin();

            foreach (var callable in callables)
            {
                if (callable.IsNull()) continue;
                var to = callable.transform.position;
                DrawGoldenConnection(from, to, callable.name);
            }
        }

        private Vector3 GetGizmoOrigin()
        {
            return MainCollider.IsNotNull() ? MainCollider.bounds.center : transform.position;
        }

        private static void DrawGoldenConnection(Vector3 from, Vector3 to, string label)
        {
            Handles.color = CallableConnectionShadowColor;
            Handles.DrawAAPolyLine(6f, from, to);

            Handles.color = CallableConnectionColor;
            Handles.DrawAAPolyLine(3f, from, to);

            DrawConnectionEndPoint(from);
            DrawConnectionEndPoint(to);

            var labelPosition = Vector3.Lerp(from, to, 0.5f);
            DrawConnectionLabel(labelPosition, label);
        }

        private static void DrawConnectionEndPoint(Vector3 position)
        {
            Handles.color = CallableConnectionColor;
            Handles.SphereHandleCap(
                0,
                position,
                Quaternion.identity,
                0.15f,
                EventType.Repaint
            );
        }

        private static void DrawConnectionLabel(Vector3 position, string label)
        {
            if (string.IsNullOrWhiteSpace(label))
                return;

            var style = new GUIStyle(EditorStyles.boldLabel)
            {
                normal =
                {
                    textColor = CallableConnectionColor
                }
            };

            Handles.Label(position + Vector3.up * 0.25f, label, style);
        }
#endif
    }
}