using UnityEngine;

namespace Streamingle.Utils.RoughConstraints
{
    [ExecuteAlways]
    [AddComponentMenu("Streamingle Utilities/Constraints/Rough Parent Constraint")]
    public class RoughParentConstraint : RoughConstraintBase
    {
        [Header("Position")]
        public Vector3Bool constrainedPositionAxis = Vector3Bool.All;
        public Vector3 positionOffset;
        public bool positionOffsetInSourceSpace = true;

        [Header("Rotation")]
        public Vector3Bool constrainedRotationAxis = Vector3Bool.All;
        public Vector3 rotationOffset;

        protected override void ExecuteConstraint(float followT)
        {
            var blend = followT * weight;

            if (TryGetWeightedPosition(out var targetPosition))
            {
                if (positionOffsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
                {
                    targetPosition += sources[0].sourceTransform.TransformVector(positionOffset);
                }
                else
                {
                    targetPosition += positionOffset;
                }

                targetPosition = ApplyAxisMask(transform.position, targetPosition, constrainedPositionAxis);
                transform.position = Vector3.Lerp(transform.position, targetPosition, blend);
            }

            if (TryGetWeightedRotation(out var targetRotation))
            {
                targetRotation *= Quaternion.Euler(rotationOffset);
                var maskedEuler = ApplyEulerAxisMask(transform.rotation, targetRotation, constrainedRotationAxis);
                targetRotation = Quaternion.Euler(maskedEuler);
                transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, blend);
            }
        }

        protected override void CaptureOffsetsFromCurrentPose()
        {
            if (TryGetWeightedPosition(out var sourcePosition))
            {
                var delta = transform.position - sourcePosition;
                if (positionOffsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
                {
                    positionOffset = sources[0].sourceTransform.InverseTransformVector(delta);
                }
                else
                {
                    positionOffset = delta;
                }
            }

            if (TryGetWeightedRotation(out var sourceRotation))
            {
                rotationOffset = (Quaternion.Inverse(sourceRotation) * transform.rotation).eulerAngles;
            }
        }
    }
}
