using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using DG.Tweening;

namespace mGameSystem.mCamera
{
    public class CameraCtrl : MonoBehaviour
    {
        #region 单例
        public static CameraCtrl Instance { get; private set; }
        public void SetInstance()
        {
            if (Instance == null) { Instance = this; }
            else { Destroy(gameObject); }
        }

        private void Awake()
        {
            SetInstance();
        }
        #endregion

        [FoldoutGroup("状态")]
        public CameraState state;
        [FoldoutGroup("状态")]
        public CameraUpdateMode mode;

        [FoldoutGroup("组件")]
        public Transform theCameraRoot;
        [FoldoutGroup("组件")]
        public Camera theCamera;

        [FoldoutGroup("目标")]
        public Transform target;
        [FoldoutGroup("目标")]
        public Transform foreSeeTarget;
        [FoldoutGroup("目标")]
        public float foreSeeLerp = 0.2f;
        [FoldoutGroup("目标")]
        public float foreSeeLimitDis = 10f;

        [FoldoutGroup("旋转")]
        public Vector3 defaultRotation = new(46f, 0, 0);

        #region 参数
        [FoldoutGroup("参数"), PropertyOrder(0), ReadOnly]
        public Vector3 cameraPos;
        [FoldoutGroup("参数"), PropertyOrder(0)]
        public float cameraLerpRate = 0.1f;
        [FoldoutGroup("参数"), PropertyOrder(0)]
        public Vector3 targetPos;
        [FoldoutGroup("参数"), PropertyOrder(0)]
        public Vector3 targetOffset;

        [FoldoutGroup("参数"),PropertyOrder(1),PropertySpace(6)]
        public Vector3 cameraRot;

        [FoldoutGroup("参数"), PropertyOrder(2), PropertySpace(6)]
        public Vector3 appendEffect;

        #endregion

        private void FixedUpdate()
        {
            if (mode != CameraUpdateMode.FixedUpdate) return;

            if (shakeOn)
            {
                shakeTime -= Time.fixedDeltaTime;
                UpdateShake();
            }

            CalFollowVec();
            CalCameraPos();
        }
        private void LateUpdate()
        {
            if (mode != CameraUpdateMode.LateUpdate) return;

            if (shakeOn)
            {
                shakeTime -= Time.deltaTime;
                UpdateShake();
            }

            CalFollowVec();
            CalCameraPos();
        }

        public void AddCameraPos(Vector3 tarPos)
        {
            theCameraRoot.position += tarPos;
        }
        public void ChangeCameraState(CameraState newState)
        {
            state = newState;
        }
        public void DoCamearaLerp(Vector3 tarPos, Ease ease = Ease.InOutQuad,UnityEngine.Events.UnityAction onComplete = null)
        {

        }
        #region 摄像机平移
        [FoldoutGroup("摄像机平移")]
        public Vector3 defaultTarOffset;

        public void ChangeCameraOffsetTo(Vector3 offset)
        {
            targetOffset = offset;
        }

        #endregion
        #region 摄像机旋转
        public void CameraRotateToDefault(float rotateLerpTime = 0.3f)
        {
            theCamera.transform.DOKill();
            theCamera.transform.DORotate(defaultRotation, rotateLerpTime).SetEase(Ease.InOutCubic);
        }
        public void CameraRotateTo(Vector3 tarRot, float rotateLerpTime = 0.3f)
        {
            theCamera.transform.DOKill();
            theCamera.transform.DORotate(tarRot, rotateLerpTime).SetEase(Ease.InOutCubic);
        }


        #endregion
        #region 计算方法
        private void CalFollowVec()
        {
            if (state == CameraState.FollowTarget) targetPos = target.position;
            else if(state == CameraState.FollowForeSee)
            {
                Vector3 dir = foreSeeTarget.position - target.position;
                float dis = Mathf.Min(dir.magnitude, foreSeeLimitDis);
                targetPos = Vector3.Lerp(
                    target.position
                    , target.position + dir.normalized * dis
                    , foreSeeLerp
                    );
            }

        }
        private void CalCameraPos()
        {
            if (state == CameraState.Freeze) return;
            cameraPos = Vector3.Lerp(cameraPos, targetPos + targetOffset, cameraLerpRate);
            cameraPos += appendEffect;
            
            theCameraRoot.position = cameraPos;

            appendEffect = Vector3.zero;
        }

        #endregion
        #region 特别效果
        #region 镜头横向冲击
        [FoldoutGroup("特别效果"), Title("镜头横向冲击")]
        public Transform theCameraImpRoot;
        [Button("DoCamImpulse")]
        public void DoCamImpulse(Vector3 imp,float impTime = 0.3f)
        {
            theCameraImpRoot.transform.DOKill();
            theCameraImpRoot.transform.DOLocalPath(
                new Vector3[] { imp, Vector3.zero }
                , impTime
            ).SetEase(Ease.InOutFlash);
        }
        #endregion
        #region 镜头抖动
        [FoldoutGroup("特别效果"),Title("镜头抖动")] public bool shakeOn;
        [FoldoutGroup("特别效果")] public float shakeStrength;
        [FoldoutGroup("特别效果")] public float shakeTimeMax = 2f;
        [FoldoutGroup("特别效果")] public float shakeTime;
        [FoldoutGroup("特别效果")] public AnimationCurve shakeCurve;
        [Button("DoShake")]
        public void DoShake(float strength = 3f,float stime = 1f)
        {
            shakeOn = true;
            shakeTime = stime;
            shakeStrength = strength;
        }
        private void UpdateShake()
        {
            if(shakeTime <= 0) { shakeOn = false;return; }
            appendEffect += UnityEngine.Random.insideUnitSphere
                * shakeStrength
                * shakeCurve.Evaluate(shakeTime / shakeTimeMax);
        }
        #endregion
        #region 镜头微冲击倾斜
        [FoldoutGroup("特别效果"), Title("镜头微冲击倾斜")]
        public Transform theCameraImpRot;
        [FoldoutGroup("特别效果")]
        public Ease cameraImpRotEase_GO = Ease.InOutCirc;
        [FoldoutGroup("特别效果")]
        public Ease cameraImpRotEase_Back = Ease.OutBounce;
        [FoldoutGroup("特别效果")]
        public const float impRotStrength = -5f;
        [FoldoutGroup("特别效果")]
        public const float impRotTime = 0.7f;
        [FoldoutGroup("特别效果")]
        public float inOutRate = 0.1f;

        [Button("DoCamImpulseRot")]
        public void DoCamImpulseRot(bool right,float strength = impRotStrength,float time = impRotTime)
        {
            theCameraImpRot.DOKill();
            var s = DOTween.Sequence();
            s.Append(theCameraImpRot.DOLocalRotate((right ? Vector3.down : Vector3.up) * strength, time * inOutRate)
                .SetEase(cameraImpRotEase_GO));
            s.Append(theCameraImpRot.DOLocalRotate(Vector3.zero, time * (1-inOutRate))
                .SetEase(cameraImpRotEase_Back));
        }
        #endregion
        #endregion


    }
    public enum CameraState
    {
        Freeze,
        FollowTarget,
        FollowForeSee,
    }
    public enum CameraUpdateMode
    {
        LateUpdate,
        FixedUpdate,
    }
}

