/**
 * @since Last modified: 2024-09-10 09:38:31
 * @function delay
 * @description Delayed the code fragment, which can replace seTimeout.The ax.frame value will change and return to zero when done.
 * @param {object} options - Parameters of delay.
 * @param  {string} options.duration - Duration of delay.The unit is ms.
 * @param  {function} [options.todo] - The cb function at the start.
 * @param  {function} [options.doing] - The cb function in progress.
 * @param  {function} [options.done] - The cb function at the end.
 * @param  {string} [options.frame=0] - Incremental animation frames.
 * @returns  {Promise}  - The Promise.
 * @see {@link https://codepen.io/axui/pen/BaMqzbb|demo @ codepen}
 * @example
 * ax.delay({duration:2000,done:()=>{}});
 * <!--return Promise-->
 * ax.delay(...).then(()=>{console.log('done,resolve')},()=>{console.log('doing,reject')})
 */
'use strict';
import { T_fn } from "../../../types/ax";
const delay = function ({ duration = 2000,todo, doing, done,frame=0 }: { duration: number,todo?:T_fn, doing?: T_fn, done?: T_fn,frame?:number }): Promise<number> {
    if (duration < 0) Promise.reject(new Error('Invalid duration'));
    todo && todo(frame);
    return new Promise((resolve, reject) => {
        try {
            if (!duration) {
                done && done(frame);
                resolve(frame);
            }
            let deadline = Date.now() + duration,
                listen = () => {
                    let newTime = Date.now();
                    if (newTime >= deadline) {
                        cancelAnimationFrame(frame);
                        done && done(frame);
                        resolve(frame);
                        frame = 0;
                    } else {
                        frame = requestAnimationFrame(listen);
                        doing && doing(frame);
                    }
                }
            listen();
        } catch (e) {
            reject(e);
        }
    });
}
export default delay;
