using System;
using UnityEngine;

namespace VOID.Generic.Trajectory
{
    [Serializable]
    public abstract class AbstractTrajectory
    {
        public Vector3 startPosition { get; protected set; }
        public Vector3 endPosition { get; protected set; }
        public float lineDistance { get; protected set; }
        public float trajectoryDistance { get; protected set; }

        public AbstractTrajectory Clone()
        {
            return MemberwiseClone() as AbstractTrajectory;
        }

        /// <summary>
        /// Initialize (again) whole trajectory.
        /// </summary>
        public void Init(Vector3 startPosition, Vector3 endPosition)
        {
            this.startPosition = startPosition;
            this.endPosition = endPosition;
            lineDistance = Vector3.Distance(startPosition, endPosition);
            trajectoryDistance = lineDistance;
            
            OnInit();
        }

        /// <returns>Position on trajectory, by given distance (in line)</returns>
        public Vector3 GetPositionByDistance(float distance)
        {
            return GetPositionByProgress(GetProgressForDistance(distance));
        }

        /// <returns>Progress (0-1) to end position, by given distance (in line)</returns>
        public virtual float GetProgressForDistance(float currentDistance)
        {
            return Mathf.Clamp01(currentDistance / lineDistance); 
        }
        
        /// <returns>Whole trajectory path with given number of points</returns>
        public Vector3[] GetPositions(int count)
        {
            var positions = new Vector3[count];
            var step = 1f / (count-1);

            for (var i = 0; i < count; i++)
                positions[i] = GetPositionByProgress(i * step);

            return positions;
        }
        
        protected abstract void OnInit();
        public abstract Vector3 GetPositionByProgress(float progress);
    }
}