/**
 * Anime.js - utils - ESM
 * @version v4.5.0
 * @license MIT
 * @copyright 2026 - Julian Garnier
 */

import { noop } from '../core/consts.js';
import { globals } from '../core/globals.js';
import { isFnc, isUnd } from '../core/helpers.js';
import { Timer } from '../timer/timer.js';

/**
 * @import {
 *   Callback,
 *   Tickable,
 * } from '../types/index.js'
*/

/**
 * @param  {Callback<Timer>} [callback]
 * @return {Timer}
 */
const sync = (callback = noop) => {
  return new Timer({ duration: 1 * globals.timeScale, onComplete: callback }, null, 0).resume();
};

/**
 * @template {Tickable | ((...args: any[]) => void) | void} T
 * @param  {(...args: any[]) => T} constructor
 * @return {(...args: any[]) => T extends void ? () => void : T}
 */
const keepTime = constructor => {
  /** @type {Tickable} */
  let tracked;
  return /** @type {(...args: any[]) => T extends void ? () => void : T} */(/** @type {*} */((...args) => {
    let currentIteration, currentIterationProgress, reversed, alternate, startTime;
    if (tracked) {
      currentIteration = tracked.currentIteration;
      currentIterationProgress = tracked.iterationProgress;
      reversed = tracked.reversed;
      alternate = tracked._alternate;
      startTime = tracked._startTime;
      tracked.revert();
    }
    const cleanup = constructor(...args);
    if (cleanup && !isFnc(cleanup) && cleanup.revert) tracked = cleanup;
    if (!isUnd(currentIterationProgress)) {
      /** @type {Tickable} */(tracked).currentIteration = currentIteration;
      /** @type {Tickable} */(tracked).iterationProgress = (alternate ? !(currentIteration % 2) ? reversed : !reversed : reversed) ? 1 - currentIterationProgress : currentIterationProgress;
      /** @type {Tickable} */(tracked)._startTime = startTime;
    }
    return cleanup || noop;
  }));
};

export { keepTime, sync };
