using UnityEngine;

namespace pdinklag.CPW.Common
{
    /// <summary>
    /// Abstract base for prop deformations.
    /// </summary>
    [RequireComponent(typeof(BodyLocation))]
    public abstract class PropDeform : MonoBehaviour
    {
        /// <summary>
        /// Contains the vertices that are affected by this deformation.
        /// Vertices not included here will not be deformed at all.
        /// </summary>
        [HideInInspector]
        public ItemSelection AffectedVertices;

        /// <summary>
        /// Computes the influence (0 to 1) of this deformation on the given vector.
        /// </summary>
        /// <param name="v">a vector in local space</param>
        public abstract float Influence(Vector3 v);

        /// <summary>
        /// Performs precomputations for deforming the prop's mesh to a target body using subsequent calls to Deform.
        /// 
        /// This is done before each of the vertices is deformed and allows to precompute anything that can be precomputed,
        /// so vertex deformation becomes faster.
        /// </summary>
        /// <param name="target">the target body</param>
        public abstract void PrepareDeform(BodyDescription target);

        /// <summary>
        /// Computes the deformation vector for a vector.
        /// </summary>
        /// <param name="v">a vector in local space</param>
        /// <param name="target">the target body</param>
        protected abstract Vector3 Deform(Vector3 v, BodyDescription target);

        /// <summary>
        /// Computes the deformation vector for a vertex.
        /// </summary>
        /// <param name="vertexNumber">the vertex number; used to decide whether the vertex is affected at all</param>
        /// <param name="vertexPos">the vertex position in local space</param>
        /// <param name="target">the target body</param>
        public Vector3 Deform(int vertexNumber, Vector3 vertexPos, BodyDescription target)
            => AffectedVertices.IsSelected(vertexNumber, true) ? Deform(vertexPos, target) : Vector3.zero;
    }
}
