using Intrepid.Core.Grounding;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Temporary
{
    public class TestGroundMorion : GroundProfileMotionBehaviour
    {
        [GroupConfigurations, SerializeField] private Vector3 localDirection = Vector3.right;
        [GroupConfigurations, SerializeField] private float speed = 2f;
        [GroupConfigurations, SerializeField] private float maxDistance = 4f;
        [GroupConfigurations, SerializeField] private bool pingPong = true;
        [GroupConfigurations, SerializeField] private bool moveOnStart;

        public Vector3 Velocity
        {
            get => GroundProfileMotion.Velocity;
            private set => GroundProfileMotion.Velocity = value;
        }
        public Vector3 DeltaPosition
        {
            get => GroundProfileMotion.DeltaPosition;
            private set => GroundProfileMotion.DeltaPosition = value;
        }
        public bool IsMoving
        {
            get => GroundProfileMotion.IsMoving;
            private set => GroundProfileMotion.IsMoving = value;
        }
        public bool IsStatic
        {
            get => GroundProfileMotion.IsStatic;
            private set => GroundProfileMotion.IsStatic = value;
        }

        private Vector3 _startPosition;
        private Vector3 _lastPosition;
        private int _directionSign = 1;
        private bool _initialized;

        private void Awake()
        {
            Snap();

            if (moveOnStart)
            {
                Move();
            }
        }

        private void FixedUpdate()
        {
            if (!IsMoving)
            {
                ClearFrameMotion();
                return;
            }

            var current = transform.position;

            var worldDirection = transform.TransformDirection(localDirection.normalized);
            var next = current + worldDirection * (_directionSign * speed * Time.fixedDeltaTime);

            if (maxDistance > 0f)
            {
                var distanceFromStart = Vector3.Dot(
                    next - _startPosition,
                    worldDirection
                );

                if (Mathf.Abs(distanceFromStart) >= maxDistance)
                {
                    if (pingPong)
                    {
                        _directionSign *= -1;

                        var clampedDistance = Mathf.Clamp(
                            distanceFromStart,
                            -maxDistance,
                            maxDistance
                        );

                        next = _startPosition + worldDirection * clampedDistance;
                    }
                    else
                    {
                        next = _startPosition + worldDirection * (Mathf.Sign(distanceFromStart) * maxDistance);
                        Stop();
                    }
                }
            }

            transform.position = next;

            DeltaPosition = transform.position - _lastPosition;
            Velocity = DeltaPosition / Time.fixedDeltaTime;

            _lastPosition = transform.position;
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void Move()
        {
            if (!_initialized)
            {
                Snap();
            }

            IsMoving = true;
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void Stop()
        {
            IsMoving = false;
            ClearFrameMotion();
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void Reverse()
        {
            _directionSign *= -1;
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void Snap()
        {
            _startPosition = transform.position;
            _lastPosition = transform.position;
            _directionSign = 1;
            ClearFrameMotion();
            _initialized = true;
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void ResetToStart()
        {
            transform.position = _startPosition;
            _lastPosition = transform.position;
            _directionSign = 1;
            ClearFrameMotion();
        }

        private void ClearFrameMotion()
        {
            DeltaPosition = Vector3.zero;
            Velocity = Vector3.zero;
        }

#if UNITY_EDITOR
        private void OnDrawGizmosSelected()
        {
            var origin = _initialized ? _startPosition : transform.position;
            var worldDirection = transform.TransformDirection(localDirection.normalized);

            Gizmos.color = Color.green;
            Gizmos.DrawLine(
                origin - worldDirection * maxDistance,
                origin + worldDirection * maxDistance
            );

            Gizmos.DrawSphere(origin - worldDirection * maxDistance, 0.08f);
            Gizmos.DrawSphere(origin + worldDirection * maxDistance, 0.08f);

            Gizmos.color = Color.cyan;
            Gizmos.DrawLine(
                transform.position,
                transform.position + Velocity
            );
        }
#endif
    }
}