using System.Collections;
using UnityEngine;

namespace Shooter.Gameplay
{
    /// <summary>
    /// Управление игроком: чтение ввода (движение стрелками, огонь, наведение мышью
    /// на землю) и спавн персонажа от чекпойнта. Сам персонаж — это
    /// <see cref="PlayerChar"/>, которого этот класс создаёт в <see cref="Respawn"/>.
    ///
    /// Многие поля Input_* и методы ниже — задел «конструктора»: опциональные действия
    /// (граната, рывок, смена оружия, полёт, транспорт), которые включаются в Главе 4.
    /// </summary>
    public class PlayerControl : MonoBehaviour
    {
        public static PlayerControl MainPlayerController;

        [Header("Спавн и префаб игрока")]
        [Tooltip("Точка появления в начале уровня")]
        public Transform m_SpawnPoint;
        [Tooltip("Префаб персонажа, создаётся при спавне")]
        public GameObject PlayerPrefab1;

        [Header("Прицел")]
        [Tooltip("Маркер точки прицеливания на земле (под курсором)")]
        public Transform m_AimPointTransofrm;

        [Header("Идентификация (задел под мультиплеер)")]
        public int ControllerNum = 0;
        public bool m_IsDead = false;

        // --- Ссылки и счётчики во время игры ---
        [HideInInspector] public PlayerChar MyPlayerChar;
        [HideInInspector] public GameObject MyPlayerPlane;
        [HideInInspector] public PlayerControl OtherControl;
        [HideInInspector] public int m_GemCount = 0;
        [HideInInspector] public string PlayerName = "Player";
        [HideInInspector] public int Kills = 0;
        [HideInInspector] public bool m_IsOnFoot = false;
        [HideInInspector] public bool UsingPowerWeapon = false;

        [HideInInspector] public Vector3 ReticlePosition;
        [HideInInspector] public Transform NextSpawnPoint;
        [HideInInspector] public Vector3 LastDeathPosition;

        // Оружие на стороне контроллера (задел; активное оружие живёт в PlayerChar).
        [HideInInspector] public Weapon_Base[] MainWeapons = new Weapon_Base[2];
        [HideInInspector] public int CurrentWeaponNum = 0;
        [HideInInspector] public Weapon_Base CurrentWeapon;

        // Номер состояния и время его начала (простая машина состояний игрока).
        [HideInInspector] public int State = 0;
        [HideInInspector] public float StateStartTime = 0;

        // --- Ввод этого кадра ---
        // Часть полей читается всегда (движение, огонь, прицел), часть — задел под
        // опциональные действия Главы 4 (граната, рывок, смена оружия, полёт и т.п.).
        [HideInInspector] public bool InputEnable = true;
        [HideInInspector] public Vector3 m_Input_Movement;
        [HideInInspector] public Vector3 AimPosition;
        [HideInInspector] public Vector2 m_CameraAngle;
        [HideInInspector] public bool Input_Fire = false;
        [HideInInspector] public bool Input_FireHold = false;
        [HideInInspector] public bool Input_HoldAim = false;
        [HideInInspector] public bool Input_Grenade = false;
        [HideInInspector] public bool Input_Force = false;
        [HideInInspector] public bool Input_Dash = false;
        [HideInInspector] public bool Input_ChangeWeapon = false;
        [HideInInspector] public bool Input_Interact = false;
        [HideInInspector] public bool Input_Fly = false;
        [HideInInspector] public bool[] Input_Detonate;

        private bool SelectedSpawnPoint = false;

        void Awake()
        {
            MainPlayerController = this;
        }

        void Start()
        {
            InputEnable = true;
            MainWeapons = new Weapon_Base[2];

            State = 0;
            StateStartTime = Time.time;
            m_IsOnFoot = true;
            Respawn();
        }

        void Update()
        {
            UpdateInputs();

            #region Опциональная фича: переключение в режим полёта (Глава 4)
            //if (Input_Fly)
            //{
            //    if (m_IsOnFoot) StartCoroutine(Co_EnterPlane());
            //    else            StartCoroutine(Co_ExitPlane());
            //}
            #endregion

            // Персонаж погиб → запускаем гибель игрока (ровно один раз).
            if (!m_IsDead && PlayerChar.m_Current.m_IsDead)
            {
                m_IsDead = true;
                GameControl.m_Current.HandlePlayerDeath();
            }
        }

        public void UpdateInputs()
        {
            // Сбрасываем ввод этого кадра (включая задел под опциональные действия).
            m_Input_Movement = Vector3.zero;
            Input_Fire = false;
            Input_FireHold = false;
            Input_Interact = false;
            Input_HoldAim = false;
            Input_Grenade = false;
            Input_Fly = false;
            Input_Dash = false;
            Input_ChangeWeapon = false;
            Input_Detonate = new bool[4];

            // Движение задаётся относительно поворота камеры.
            Vector3 cameraForward = CameraControl.m_Current.transform.forward;
            cameraForward.y = 0;
            cameraForward.Normalize();
            Vector3 cameraRight = Helper.RotatedVector(90, cameraForward);

            if (Input.GetKey(KeyCode.UpArrow))
                m_Input_Movement += cameraForward;
            else if (Input.GetKey(KeyCode.DownArrow))
                m_Input_Movement -= cameraForward;

            if (Input.GetKey(KeyCode.LeftArrow))
                m_Input_Movement -= cameraRight;
            else if (Input.GetKey(KeyCode.RightArrow))
                m_Input_Movement += cameraRight;

            if (Input.GetKey(KeyCode.Z))
                Input_FireHold = true;

            #region Опциональные действия игрока (Глава 4) — раскомментируйте, чтобы включить
            //if (Input.GetKey(KeyCode.X) || Input.GetMouseButton(0)) Input_FireHold = true;
            //if (Input.GetMouseButton(1)) Input_HoldAim = true;
            //if (Input.GetKeyDown(KeyCode.E)) Input_Interact = true;
            //if (Input.GetKeyDown(KeyCode.G)) Input_Grenade = true;
            //if (Input.GetKeyDown(KeyCode.R)) Input_Dash = true;
            //if (Input.GetKeyDown(KeyCode.T)) Input_Force = true;
            //if (Input.GetKeyDown(KeyCode.Q)) Input_ChangeWeapon = true;
            //if (Input.GetKeyDown(KeyCode.Space)) Input_Fly = true;
            //if (Input.GetKeyDown(KeyCode.Alpha1)) Input_Detonate[0] = true;
            //if (Input.GetKeyDown(KeyCode.Alpha2)) Input_Detonate[1] = true;
            //if (Input.GetKeyDown(KeyCode.Alpha3)) Input_Detonate[2] = true;
            //if (Input.GetKeyDown(KeyCode.Alpha4)) Input_Detonate[3] = true;
            #endregion

            // Наведение: точка под курсором, спроецированная на землю (плоскость Y=0).
            Ray ray = CameraControl.m_Current.m_MyCamera.ScreenPointToRay(Input.mousePosition);
            new Plane(Vector3.up, Vector3.zero).Raycast(ray, out float dis);
            AimPosition = ray.origin + dis * ray.direction;
            m_AimPointTransofrm.position = AimPosition;
            ReticlePosition = m_AimPointTransofrm.position;
        }

        public void Kill()
        {
            m_IsDead = true;
        }

        public void EnablePlayer(bool enable)
        {
            MyPlayerChar.gameObject.SetActive(enable);
        }

        public void Respawn()
        {
            GameObject obj = Instantiate(PlayerPrefab1);
            MyPlayerChar = obj.GetComponent<PlayerChar>();

            if (GameControl.m_Current.m_MainSaveData.m_CheckpointNumber == 0)
            {
                MyPlayerChar.transform.position = m_SpawnPoint.position + new Vector3(0, .1f, 0);
            }
            else
            {
                int num = GameControl.m_Current.m_MainSaveData.m_CheckpointNumber - 1;
                MyPlayerChar.transform.position = CheckpointControl.m_Main.m_Checkpoints[num].m_SpawnPoint.position;
            }

            State = 1;
            StateStartTime = Time.time;
        }

        public void GiveWeapon(int num, int ammo)
        {
            MainWeapons[num].AmmoCount = ammo;
            MainWeapons[num].WeaponEnable = true;

            CurrentWeaponNum = num;
            CurrentWeapon = MainWeapons[num];
        }

        #region Опциональная фича: режим полёта/самолёта (Глава 4)
        // Включается переключателем Input_Fly в Update. Для работы нужен префаб
        // самолёта (поле было закомментировано в исходном шаблоне) и его спавн в Respawn.
        public IEnumerator Co_EnterPlane()
        {
            MyPlayerPlane.gameObject.SetActive(true);
            MyPlayerChar.GetComponent<Rigidbody>().isKinematic = true;
            MyPlayerPlane.GetComponent<Rigidbody>().isKinematic = true;

            Vector3 pos1 = MyPlayerChar.transform.position;
            Vector3 pos2 = pos1;
            pos2.y = 30f;
            MyPlayerPlane.transform.position = pos2;

            float counter = 0;
            while (counter < 1)
            {
                MyPlayerChar.transform.position = Vector3.Lerp(pos1, pos2, counter);
                counter += 0.02f;
                yield return null;
            }

            MyPlayerChar.transform.position = pos2;
            MyPlayerChar.gameObject.SetActive(false);
            MyPlayerPlane.GetComponent<Rigidbody>().isKinematic = false;
            m_IsOnFoot = false;
            yield return null;
        }

        public IEnumerator Co_ExitPlane()
        {
            MyPlayerChar.gameObject.SetActive(true);
            MyPlayerChar.GetComponent<Rigidbody>().isKinematic = true;
            MyPlayerPlane.GetComponent<Rigidbody>().isKinematic = true;

            Vector3 pos1 = MyPlayerPlane.transform.position;
            MyPlayerChar.transform.position = pos1;
            Vector3 pos2 = pos1;
            pos2.y = 0.1f;

            float counter = 0;
            while (counter < 1)
            {
                MyPlayerChar.transform.position = Vector3.Lerp(pos1, pos2, counter);
                counter += 0.02f;
                yield return null;
            }

            MyPlayerChar.transform.position = pos2;
            MyPlayerChar.GetComponent<Rigidbody>().isKinematic = false;
            MyPlayerPlane.gameObject.SetActive(false);
            m_IsOnFoot = true;
            yield return null;
        }
        #endregion

        #region Опциональные фичи: транспорт и выбор точки спавна (Глава 4)
        // Заготовки под въезд/выезд из транспорта и поиск безопасной точки спавна
        // (для кооператива). В шаблоне тела были закомментированы — оставлены как стабы.
        public void EnterVehicle() { }

        public void ExitVehicle() { }

        public void FindSpawnPoint() { }
        #endregion
    }
}
