using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Splines;

namespace Pursuit.MonoBehaviours
{
    public class ParentedSpline : ContextBehaviour
    {
        [SerializeField] private SplineContainer splineContainer;

        [SerializeField] private List<Transform> transforms;

        private readonly List<BezierKnot> knots = new();

        [NonSerialized] private readonly bool mode = false;
        private readonly List<Vector3> positionOffsets = new();
        private readonly List<Quaternion> rotationOffsets = new();

        private void Awake()
        {
            Setup();
        }

        protected override void Update()
        {
        }

        private void LateUpdate()
        {
            Transform splineTransform = splineContainer.transform;
            Spline spline = splineContainer.Spline;

            for (int index = 0; index < spline.Count; ++index)
            {
                BezierKnot knot = spline[index];
                Transform parent = transforms[index];

                Vector3 positionOffset = parent.TransformPoint(positionOffsets[index]);
                knot.Position = splineTransform.InverseTransformPoint(positionOffset);

                knot.Rotation = Quaternion.Inverse(splineTransform.rotation) * parent.transform.rotation *
                                rotationOffsets[index];

                knots[index] = knot;

                if (mode)
                    spline.SetKnot(index, knot);
            }

            if (!mode)
                spline.SetKnots(knots);
        }

        [ContextMenu("Recalculate")]
        private void Setup()
        {
            Transform splineTransform = splineContainer.transform;
            Spline spline = splineContainer.Spline;
            knots.Clear();
            positionOffsets.Clear();
            rotationOffsets.Clear();
            knots.AddRange(spline.Knots);

            for (int index = 0; index < spline.Count; ++index)
            {
                BezierKnot knot = knots[index];
                Transform parent = transforms[index];
                positionOffsets.Add(parent.InverseTransformPoint(splineTransform.TransformPoint(knot.Position)));

                Quaternion knotWorldRotation = splineTransform.rotation * knot.Rotation;
                Quaternion toParentRotation = Quaternion.Inverse(parent.transform.rotation) * knotWorldRotation;
                rotationOffsets.Add(toParentRotation);
            }
        }
    }
}