using System.Collections.Generic;
using System.Linq;
using AnimationMechanics;
using Core.Common;
using Core.Common.ObjectParameters;
using Core.Common.ObjectParameters.Extensions;
using Core.Extensions;
using Helpers;
using Helpers.GameObjects;
using NPZ.InputHandler;
using NPZ.ObjectActivatorDeactivator;
using NPZ.PickItemInventoryMechanicRuntime;
using NPZ.TriggerHandlers;
using ScenarioGenerator.Models;
using UI;
using UI.GameMechanic;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;

namespace NPZ.PickItemInventoryMechanicEditor
{
    public static class PickItemInventoryMechanicBuilder
    {
        private const float TransitionDuration = 0.1f;

        private const string ActiveObjectPrefix = "ActiveObject";
        private const string AdditionalObjectPrefix = "AdditionalObject";

        public static GameObject BuildMechanic(Transform target, Action action, TypeMenuElement typeMenuElement)
        {
            var newMechanic = SetupMechanic(target, action, typeMenuElement);

            return newMechanic.gameObject;
        }

        private static GameObject SetupMechanic(Transform target, Action action, TypeMenuElement typeMenuElement)
        {
            if (target.transform.childCount < 1)
            {
                Debug.LogError($"Ошибка при генерации механики откручивания {target.name}: нет дочерних объектов");
                return null;
            }

            var targetChild = target.Cast<Transform>()
                .FirstOrDefault(t => t.gameObject.name
                    .StartsWith(ActiveObjectPrefix));

            var additionalChild = target.Cast<Transform>()
                .FirstOrDefault(t => t.gameObject.name
                    .StartsWith(AdditionalObjectPrefix));

            if (targetChild == null)
            {
                Debug.LogError("Не могу найти 'ActiveObject': " + target.name);
                return null;
            }

            if (target.GetComponent<ObjectNameParameter>() == null)
            {
                target.gameObject.AddComponent<ObjectNameParameter>();
            }

            var dummyMechanic = new GameObject(nameof(PickItemInventoryMechanic));
            dummyMechanic.transform.position = targetChild.position;
            dummyMechanic.transform.SetParent(targetChild);

            dummyMechanic.AddComponent<TagItem>().SetupMechanicDummyTag();

            dummyMechanic.transform.GenerateCollider(targetChild);

            SetupTemplate(dummyMechanic.transform);

            var newMechanic = new GameObject().AddComponent<PickItemInventoryMechanic>();

            var outlineHighlighter = OutlineHighlighter.CreateNew(targetChild);
            outlineHighlighter.Initialize(outlineHighlighter, newMechanic.transform, targetChild);

            var collider = dummyMechanic.GetComponent<Collider>();

            var triggerHandlerEnter = new GameObject().AddComponent<TriggerHandlerEnter>();
            triggerHandlerEnter.transform.SetParent(newMechanic.transform);
            triggerHandlerEnter.Initialize(false, TagItem.HandTag, collider);

            var triggerHandlerExit = new GameObject().AddComponent<TriggerHandlerExit>();
            triggerHandlerExit.transform.SetParent(newMechanic.transform);
            triggerHandlerExit.Initialize(false, TagItem.HandTag, collider);

            var leftTriggerPressedMechanicPrefab = Resources.Load("WaitLeftTriggerPressed") as GameObject;
            var leftTriggerPressedMechanicInstance =
                (GameObject)PrefabUtility.InstantiatePrefab(leftTriggerPressedMechanicPrefab,
                    newMechanic.transform);

            var rightTriggerPressedMechanicPrefab = Resources.Load("WaitRightTriggerPressed") as GameObject;
            var rightTriggerPressedMechanicInstance =
                (GameObject)PrefabUtility.InstantiatePrefab(rightTriggerPressedMechanicPrefab,
                    newMechanic.transform);

            var inputMechanic1 = leftTriggerPressedMechanicInstance.GetComponent<InputHandlerMechanic>();
            var inputMechanic2 = rightTriggerPressedMechanicInstance.GetComponent<InputHandlerMechanic>();

            var animationController =
                Resources.Load("PickItemInventoryAnimatorController") as AnimatorController;

            var clip = Resources.Load("PickItemInventoryAnimationClip") as AnimationClip;

            var animator = target.gameObject.GetComponent<Animator>();
            animator = animator != null ? animator : targetChild.gameObject.AddComponent<Animator>();
            // animator.runtimeAnimatorController = animationController;

            // var animationMechanic = new GameObject().AddComponent<CrossFadeAnimation>();
            // animationMechanic.transform.SetParent(newMechanic.transform);
            // animationMechanic.Initialize(animator, clip, TransitionDuration);

            var deactivator = new GameObject().AddComponent<ObjectDeactivator>();
            deactivator.transform.SetParent(newMechanic.transform);
            deactivator.Initialize(additionalChild.gameObject);

            var createRadialMenuElement = new GameObject().AddComponent<CreateRadialMenuElement>();
            createRadialMenuElement.transform.SetParent(newMechanic.transform);
            createRadialMenuElement.Initialize(typeMenuElement);

            var updateActionStatus = new GameObject().AddComponent<UpdateActionStatus>();
            updateActionStatus.transform.SetParent(newMechanic.transform);
            updateActionStatus.Initialize(action.Name);

            newMechanic.Initialize(triggerHandlerEnter,
                triggerHandlerExit,
                inputMechanic1,
                inputMechanic2,
                animator,
                deactivator,
                createRadialMenuElement,
                outlineHighlighter,
                updateActionStatus,
                dummyMechanic);

            var linkContainer = target.GetComponent<GameObjectLinkContainer>();
            linkContainer = linkContainer ? linkContainer : target.gameObject.AddComponent<GameObjectLinkContainer>();
            linkContainer.AddTarget(newMechanic.gameObject);

            newMechanic.gameObject.AddComponent<GameObjectLinkContainer>()
                .AddTarget(target.gameObject);

            return newMechanic.gameObject;
        }

        private static GameObject SetupTemplate(Transform target)
        {
            var prefab = Resources.Load("PickItemInventoryTemplate") as GameObject;
            var template = (GameObject)PrefabUtility.InstantiatePrefab(prefab, target);

            var taggedMechanic = template.GetComponent<TagItem>();

            if (taggedMechanic == null)
            {
                template.AddComponent<TagItem>().SetupMechanicTemplateTag();
            }

            return template.gameObject;
        }

        public static void ClearMechanicByGraphics(Transform target, PickItemInventoryMechanic mechanic)
        {
            Object.DestroyImmediate(mechanic.DummyMechanic);

            RemoveCollider(target);
            RemoveMechanic(target);

            var targetChild = target.Cast<Transform>()
                .Where(t => t.gameObject.name
                    .StartsWith(ActiveObjectPrefix));
            RemoveAnimators(targetChild);
        }

        public static bool TryClearMechanicByMechanic(Transform target)
        {
            if (target == null)
            {
                return false;
            }

            if (!target.TryGetComponent(out PickItemInventoryMechanic mechanic))
            {
                return false;
            }

            var graphics = target.GetComponent<GameObjectLinkContainer>().TargetsContainer[0];
            ClearMechanicByGraphics(graphics.transform, mechanic);
            return true;
        }

        private static void RemoveCollider(Transform target)
        {
            Object.DestroyImmediate(target.GetComponent<BoxCollider>());
            Object.DestroyImmediate(target.GetComponent<ColliderDataSaver>());
        }

        private static void RemoveMechanic(Transform target)
        {
            var objectParameter = target.gameObject.GetComponent<ObjectNameParameter>();

            if (objectParameter != null)
            {
                Object.DestroyImmediate(objectParameter);
            }

            var objectOpenClose = target.gameObject.AddOpenClosedParameter();

            if (objectOpenClose != null)
            {
                Object.DestroyImmediate(objectOpenClose);
            }

            var linkContainer = target.gameObject.GetComponent<GameObjectLinkContainer>();

            if (linkContainer == null)
            {
                return;
            }

            Object.DestroyImmediate(linkContainer);

            var templates = target.GetComponentsInChildren<TagItem>().Where(t => t.Tag == TagItem.MechanicDummy);

            foreach (var template in templates)
            {
                Object.DestroyImmediate(template.gameObject);
            }
        }

        private static void RemoveAnimators(IEnumerable<Transform> additionalChilds)
        {
            foreach (var child in additionalChilds)
            {
                var animator = child.gameObject.GetComponent<Animator>();

                if (animator != null)
                {
                    Object.DestroyImmediate(animator);
                }
            }
        }
    }
} смотри, нужно чтобы мы включали в box collider свойство trigger, когда берем объект и выключали, когда отпускаем его