using System;
using Script.Gameplay.Input;
using UnityEngine;
using Core;
using Script.Gameplay.Global;

namespace Script.Gameplay.Player
{
    public enum WatchMode
    {
        Normal,
        Inside,
        Outside
    }

    public class PlayerWatchModeController : MonoBehaviour
    {
        [SerializeField] private Camera cam;
        public event Action<WatchMode> OnEnterWatchMode;
        public event Action<WatchMode> OnExitWatchMode;
        private InputManager inputManager;
        private TimePauseManager timePauseManager;
        private PlayerInteractorController playerInteractorController;
        private PlayerConnectController _playerConnectController;
        private WatchMode previousMode = WatchMode.Normal;
        private WatchMode currentMode = WatchMode.Normal;

        public WatchMode CurrentWatchMode
        {
            get => currentMode;
            set
            {
                previousMode = currentMode;
                currentMode = value;
                // 触发退出事件 
                OnExitWatchMode?.Invoke(previousMode);
                OnEnterWatchMode?.Invoke(currentMode);
                
                SwitchWatchMode(currentMode);
            }
        }

        private void Start()
        {
            inputManager = InputManager.Instance;
            timePauseManager = TimePauseManager.Instance;
            playerInteractorController = GetComponent<PlayerInteractorController>();
            _playerConnectController = GetComponent<PlayerConnectController>();

            var input = inputManager.Input;
            input.Player.SwitchWatchMode.performed += ctx =>
            {
                var modeTemp = (WatchMode)(((int)CurrentWatchMode + 1) % 3);
                CurrentWatchMode = modeTemp;
            };
            ;

            ControllerLocator.Instance.Register(this);
        }

        // 实现按Tap键实现在WatchMode 3个模式切换，并通过SwitchWatchMode设置正确的相机模式
        private void SwitchWatchMode(WatchMode watchMode)
        {
            switch (watchMode)
            {
                case WatchMode.Normal:
                    SetSeeLines(false);
                    inputManager.SetCursorState(false, CursorLockMode.Locked);
                    inputManager.SetInputForLook(true);
                    inputManager.SetInputForMove(true);
                    if (timePauseManager != null)
                    {
                        timePauseManager.SetPaused(false);
                    }

                    if (playerInteractorController != null)
                    {
                        playerInteractorController.SetPlayerInteractionEnabled(true);
                    }

                    if (_playerConnectController != null)
                    {
                        _playerConnectController.IsEnableConnecting = false;
                    }

                    break;
                case WatchMode.Inside:
                    SetSeeLines(false);
                    inputManager.SetCursorState(true, CursorLockMode.Confined);
                    inputManager.SetInputForLook(false);
                    inputManager.SetInputForMove(false);
                    if (timePauseManager != null)
                    {
                        timePauseManager.SetPaused(true);
                    }

                    if (playerInteractorController != null)
                    {
                        playerInteractorController.SetPlayerInteractionEnabled(false);
                    }
                    
                    if (_playerConnectController != null)
                    {
                        _playerConnectController.IsEnableConnecting = false;
                    }

                    break;
                case WatchMode.Outside:
                    SetSeeLines(true);
                    inputManager.SetCursorState(false, CursorLockMode.Locked);
                    inputManager.SetInputForLook(true);
                    inputManager.SetInputForMove(true);
                    if (timePauseManager != null)
                    {
                        timePauseManager.SetPaused(false);
                    }

                    if (playerInteractorController != null)
                    {
                        playerInteractorController.SetPlayerInteractionEnabled(true);
                    }
                    
                    if (_playerConnectController != null)
                    {
                        _playerConnectController.IsEnableConnecting = true;
                    }

                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        private void SetSeeLines(bool seeLine)
        {
            int linesLayer = LayerMask.NameToLayer("Lines");
            int mask = cam.cullingMask;

            if (seeLine)
                mask |= 1 << linesLayer; // 打开
            else
                mask &= ~(1 << linesLayer); // 关闭

            cam.cullingMask = mask;
        }
    }
}