// FlexiMotion // https://kybernetik.com.au/flexi-motion // Copyright 2023-2025 Kybernetik //

#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.

using Unity.Jobs;
using UnityEngine;

namespace FlexiMotion.Modifiers
{
    /// <summary>A <see cref="FlexiMotionModifier"/> which immediately updates the simulation several times on startup.</summary>
    /// https://kybernetik.com.au/flexi-motion/api/FlexiMotion.Modifiers/PreWarmModifier
    /// 
    [AddComponentMenu(FMStrings.ModifiersMenuPrefix + "Pre-Warm Modifier")]
    [HelpURL(FMStrings.DocsURLs.ModifiersAPIDocumentation + "/" + nameof(PreWarmModifier))]
    [DefaultExecutionOrder(ExecutionTime)]
    public class PreWarmModifier : FlexiMotionModifier,
        JobModifierGroup.IOnInitialize
    {
        /************************************************************************************************************************/

        /// <summary>Execute after other modifiers register and initialize.</summary>
        public const int ExecutionTime = 5000;

        /************************************************************************************************************************/

        [SerializeField, Range(1, 25)]
        [Tooltip("The number of iterations to execute")]
        private int _Iterations = 3;

        /// <summary>[<see cref="SerializeField"/>] The number of iterations to execute.</summary>
        public int Iterations => _Iterations;

        [SerializeField, Range(0, 1)]
        [Tooltip("The delta time value to use. If 0, the standard Time.fixedDeltaTime will be used.")]
        private float _DeltaTime;

        /// <summary>[<see cref="SerializeField"/>]
        /// The delta time value to use. If 0, the standard <see cref="Time.fixedDeltaTime"/> will be used.
        /// </summary>
        public new float DeltaTime => _DeltaTime;

        /************************************************************************************************************************/

        /// <inheritdoc/>
        protected override void OnValidate()
        {
            base.OnValidate();

            _DeltaTime = Mathf.Clamp01(_DeltaTime);

            if (_Iterations < 1)
                _Iterations = 1;
        }

        /************************************************************************************************************************/

        /// <inheritdoc/>
        protected override void Enable(JobModifierGroup modifiers)
        {
            base.Enable(modifiers);

            modifiers.AddOnInitialize(ExecutionTime, this);
        }

        /************************************************************************************************************************/

        /// <inheritdoc/>
        protected override bool Disable(JobModifierGroup modifiers)
        {
            base.Disable(modifiers);

            return modifiers.OnInitialize.Remove(ExecutionTime);
        }

        /************************************************************************************************************************/

        /// <inheritdoc/>
        public virtual JobHandle OnInitialize(JobHandle dependsOn = default)
        {
            var deltaTime = _DeltaTime > 0
                ? _DeltaTime
                : Time.fixedDeltaTime;

            for (int i = 0; i < _Iterations; i++)
                dependsOn = Target.Runtime.ScheduleJob(deltaTime, dependsOn);

            return dependsOn;
        }

        /************************************************************************************************************************/
    }
}

