using DG.Tweening;
using System;
using UnityEngine;
using XGame.Framework.Interfaces;
using XGame.Framework.Time;

namespace FL.Battle.Actions
{
    /// <summary>
    /// 贝塞尔移动
    /// 中心点位置随机
    /// </summary>
    internal class MoveBezierAction : IAction, IPauseable, ITimeScalable
    {
        public MoveActionArgs args;
        private Tween _tween;
        private bool _paused;

        float ITimeScalable.TimeScale
        {
            get => _tween?.timeScale ?? 1;
            set
            {
                if (_tween == null)
                {
                    return;
                }
                _tween.timeScale = value;
            }
        }

        void IReference.Clear()
        {
            _tween?.Kill();
            _tween = null;
            args = default;
            _paused = false;
        }
        public void Start(Transform transform, bool isFoword)
        {
            //transform.DOPlayForward();
            // 贝塞尔曲线运动
            transform.position = args.from;
            var timeScale = UnityEngine.Random.Range(0.2f, 0.8f);
            var linePoint = Vector3.Lerp(args.from, args.to, timeScale);
            var dir = Vector3.Cross(args.to - args.from, Vector3.forward).normalized; //运动方向的法线
            // 沿Y轴上下运动时算出来z值为零，直接把x值赋值给z进行偏移
            if (dir.z == 0)
                dir.z = dir.x;
            var disOffset = UnityEngine.Random.Range(-3f, 3f);
            var center = linePoint + dir * disOffset;
            var totalTime = args.duration * 0.001f;
            var timeTween = DOTween.To(() => 0, (t) =>
            {
                var tNormal = t / totalTime;
                var pos = args.from.BezierPoint(center, args.to, tNormal);
                transform.position = pos;
                if (isFoword)
                {
                    var tempDir = (args.to - pos).normalized;
                    var rot = Vector3.zero;
                    rot.z = Vector3.Angle(tempDir, Vector3.up);
                    transform.localEulerAngles = rot;
                    //if (tempDir != Vector3.zero)
                    //{
                    //    transform.forward = tempDir;
                    //}
                }
                args.onUpdate.SafeInvoke(pos);
            }, totalTime, totalTime);
            if (args.delay > 0)
                timeTween.SetDelay(args.delay * 0.001f);
            timeTween.SetEase(args.ease == Ease.Unset ? Ease.OutQuad : args.ease);
            _tween = timeTween;
            timeTween.onComplete = () =>
            {
                var callback = args.onComplete;
                _tween = null;
                args = default;
                callback?.Invoke();
            };
        }
        void IAction.Start(Transform transform)
        {
            Start(transform, true);
        }
        void IPauseable.Pause()
        {
            if (_tween == null || _paused)
            {
                return;
            }
            _paused = true;
            _tween.Pause();
        }
        void IPauseable.Resume()
        {
            if (_paused)
            {
                _paused = false;
                _tween?.Play();
            }
        }
    }
}
