using System;
using UnityEngine;

namespace Gyvr.Mythril2D
{
    [Serializable]
    public class MountController : AController<Mount>
    {
        [Header("Mount Sprite Settings")]
        [SerializeField] private Vector2 m_mountOffset = Vector2.zero;
        [SerializeField] private Vector2 m_mountedColliderSize = new(1.5f, 1f);
        [SerializeField] private Vector2 m_mountedColliderOffset = new(0f, -0.2f);

        [Header("Dismount Settings")]
        [SerializeField] private bool m_dismountOnDamage = false;
        [SerializeField] private float m_remountCooldown = 2.0f;
        [SerializeField] private float m_destroyDistance = 20f;

        private CharacterBase m_master;
        private CapsuleCollider2D m_playerCollider;
        private Vector2 m_originalColliderSize;
        private Vector2 m_originalColliderOffset;

        public float RemountCooldown => m_remountCooldown;
        public bool DismountOnDamage => m_dismountOnDamage;
        public float DestroyDistance => m_destroyDistance;

        protected override void OnStart()
        {
            base.OnStart();

            if (m_subject != null)
            {
                m_subject.SetMovementDirection(Vector2.zero);
                m_subject.SetLookAtDirection(Vector2.right);
            }
        }

        public void ClearStaleOrders()
        {
            m_subject.MoveTo(m_subject.transform.position);
            m_subject.ResetTargetDirection();
            m_subject.InterruptPush();
        }

        protected override void OnInitialize()
        {
            base.OnInitialize();
            GameManager.NotificationSystem.mapLoaded.AddListener(ClearStaleOrders);
        }

        protected override void OnTerminate()
        {
            GameManager.NotificationSystem.mapLoaded.RemoveListener(ClearStaleOrders);
            base.OnTerminate();
        }

        private Vector2 GetMasterMovementDirection()
        {
            if (!m_master || !m_master.IsMoving()) return Vector2.zero;

            Vector2 dir = Vector2.zero;
            if (m_master.IsMovingLeft()) dir.x = -1f;
            if (m_master.IsMovingRight()) dir.x = 1f;
            if (m_master.IsMovingUp()) dir.y = 1f;
            if (m_master.IsMovingDown()) dir.y = -1f;

            return dir.normalized;
        }

        public void SetMaster(CharacterBase master)
        {
            m_master = master;

            if (m_master != null)
            {
                m_playerCollider = m_master.GetComponent<CapsuleCollider2D>();

                if (m_playerCollider != null)
                {
                    m_originalColliderSize = m_playerCollider.size;
                    m_originalColliderOffset = m_playerCollider.offset;

                    m_playerCollider.size = m_mountedColliderSize;
                    m_playerCollider.offset = m_mountedColliderOffset;
                }
            }
        }

        protected override void OnUpdate()
        {
            if (!m_master)
            {
                return;
            }

            Vector3 targetPosition = m_master.transform.position + (Vector3)m_mountOffset;
            m_subject.transform.position = targetPosition;

            Vector2 moveDir = GetMasterMovementDirection();

            if (moveDir.sqrMagnitude > 0.01f)
            {
                m_subject.SetMovementDirection(moveDir);
                m_subject.SetLookAtDirection(moveDir);
            }
            else
            {
                m_subject.SetMovementDirection(Vector2.zero);
            }
        }

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

            if (m_subject != null)
            {
                m_subject.SetMovementDirection(Vector2.zero);
            }

            if (m_playerCollider != null)
            {
                m_playerCollider.size = m_originalColliderSize;
                m_playerCollider.offset = m_originalColliderOffset;
            }
        }
    }
}
