using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using Cinemachine;
namespace Game
{
    /// 
    /// 主相机及后处理在此管理
    /// 
    public class CameraManager : ManagerBase
    {
        public GameCamera MGameCamera;
        private PostProcessVolume _mPostProcessVolume;
        private Camera _mMainCamera;
        private CinemachineVirtualCamera _mMainCameraVirtual;
        private CinemachineTargetGroup _mMainCameraGroup;
        private CinemachineImpulseSource _mMainCollisionImpulseSource;
        private Transform[] _mTargets = new Transform[2];//TODO 可扩展性
        private Transform[] _mTargetsAgent = new Transform[2];//TODO 可扩展性
        public CameraManager()
        {
        }
        public override void OnCreate()
        {
            var cameraRoot = GameObject.Find("CameraRoot");
            Object.DontDestroyOnLoad(cameraRoot);
            _mMainCamera = cameraRoot.transform.Find("Camera_Main").GetComponent();
            _mMainCameraVirtual = cameraRoot.transform.Find("Camera_Virtual").GetComponent();
            _mMainCollisionImpulseSource = cameraRoot.transform.Find("Camera_Virtual").GetComponent();
            _mMainCameraGroup = cameraRoot.transform.Find("Camera_Group").GetComponent();
            _mMainCameraGroup.m_Targets = new CinemachineTargetGroup.Target[2];
            MGameCamera = _mMainCamera.GetComponent();
            MGameCamera.material.SetVector("_ScreenSize", new Vector4(Screen.width, Screen.height, 0, 0));
            _mPostProcessVolume = _mMainCamera.GetComponent();
            //TODO 有两个以上锁定目标时优化
            var newTargt0 = PrefabManager.Instance.CreateGo("CameraTarget");
            var newTargt1 = PrefabManager.Instance.CreateGo("CameraTarget");
            newTargt0.transform.parent = cameraRoot.transform;
            newTargt1.transform.parent = cameraRoot.transform;
            _mTargetsAgent[0] = newTargt0.transform;
            _mTargetsAgent[1] = newTargt1.transform;
            _mMainCameraGroup.m_Targets[0].target = _mTargetsAgent[0];
            _mMainCameraGroup.m_Targets[0].weight = 1;
            _mMainCameraGroup.m_Targets[0].radius = 2.5f;
            _mMainCameraGroup.m_Targets[1].target = _mTargetsAgent[1];
            _mMainCameraGroup.m_Targets[1].weight = 1;
            _mMainCameraGroup.m_Targets[1].radius = 2.5f;
            //默认设置 TODO 好像没有用
            // var brain = m_MainCamera.GetComponent();
            // CinemachineImpulseManager.Instance.IgnoreTimeScale = true;
            // brain.m_UpdateMethod = CinemachineBrain.UpdateMethod.LateUpdate;
            // brain.m_IgnoreTimeScale = true;
        }
        public override void Update()
        {
            UpdateCameraTarget();//更新相机锁定目标
        }
        public override void FixedUpdate()
        {
            if (Util.IsLevelLoading())
            {
                return;
            }
            // UpdataBackground();//更新差速滚轴
        }
        public override void OnDestroy() { }
        public void SetMainTarget(Transform target)
        {
            _mTargets[0] = target;
        }
        public void SetSubTarget(Transform target)
        {
            _mTargets[1] = target;
        }
        public void Shake()
        {
            _mMainCollisionImpulseSource.GenerateImpulse();
        }
        public Vector3 GetScreenPos(Vector3 pos)
        {
            var ret = _mMainCamera.WorldToScreenPoint(pos);
            ret = new Vector3(ret.x, Screen.height - ret.y, ret.z);
            return ret;
        }
        public T GetPostProcessSetting() where T : PostProcessEffectSettings
        {
            return _mPostProcessVolume.profile.GetSetting();
        }
        public CinemachineVirtualCamera GetVirtualCamera()
        {
            return _mMainCameraVirtual;
        }
        private void UpdateCameraTarget()
        {
            if (_mTargets[0] == null)
            {
                return;
            }
            if (_mTargets[1] == null)
            {
                _mTargets[1] = _mTargets[0];
            }
            _mTargetsAgent[0].position = _mTargets[0].position;
            _mTargetsAgent[1].position = _mTargets[1].position;
            ClampToLevel(_mTargetsAgent[0]);
            ClampToLevel(_mTargetsAgent[1]);
        }
        private void ClampToLevel(Transform transform)
        {
            var pos = transform.position;
            var start = pos + Vector3.up;
            var x = pos.x;
            var z = pos.z;
            RaycastHit hitInfo;
            if (Physics.Raycast(start, Vector3.back, out hitInfo, GameConst.LevelCameraOffsetZ, UtilPhysics.LayerMaskWall))
            {
                z = Mathf.Max(z, hitInfo.point.z + GameConst.LevelCameraOffsetZ);
            }
            if (Physics.Raycast(start, Vector3.left, out hitInfo, GameConst.LevelCameraOffsetX, UtilPhysics.LayerMaskWall))
            {
                x = Mathf.Max(x, hitInfo.point.x + GameConst.LevelCameraOffsetX);
            }
            else if (Physics.Raycast(start, Vector3.right, out hitInfo, GameConst.LevelCameraOffsetX, UtilPhysics.LayerMaskWall))
            {
                x = Mathf.Min(x, hitInfo.point.x - GameConst.LevelCameraOffsetX);
            }
            transform.position = new Vector3(x, 0, z);
        }
    }
    public abstract partial class Util
    {
        public static void SetMainTarget(Transform target)
        {
            CameraManager.Instance.SetMainTarget(target);
        }
        public static void SetSubTarget(Transform target)
        {
            CameraManager.Instance.SetSubTarget(target);
        }
        public static void Shake()
        {
            CameraManager.Instance.Shake();
        }
        public static Vector3 GetScreenPos(Vector3 pos)
        {
            return CameraManager.Instance.GetScreenPos(pos);
        }
        public static T GetPostProcessSetting() where T : PostProcessEffectSettings
        {
            return CameraManager.Instance.GetPostProcessSetting();
        }
        public static CinemachineVirtualCamera GetVirtualCamera()
        {
            return CameraManager.Instance.GetVirtualCamera();
        }
    }
}