/**
 * @since Last modified: 2024/05/11 11:22:38
 * @namespace plan
 * @description Plan model. Can be created, canceled and implemented. Similar to subscription/publication models.
 * @see {@link https://codepen.io/axui/pen/mdvwQYo|demo @ codepen}
 */





'use strict';
import { T_fn } from '../../../types/ax';
import getDataType from './getDataType';
import trim from './trim';
const plan: any = {
    handle: (name: any, type: string, cb: any) => {
        let nameArr: string[] = [];
        if (type === 'String') {
            name = trim(name);
            nameArr = name.includes(',') ? name.split(',') : name.split(' ');
        } else if (type === 'Array') {
            nameArr = name.map((k: string) => trim(k));
        }
        if (nameArr.length > 0) {
            for (let k of nameArr) {
                cb(k);
            }
        }
    },
    /**
 * @memberOf plan
 * @description Create a plan.
 * @param {string|string[]} name - Plan name.
 * @param {*} instance - Instance object.
 * @param {function} content - Plan content.It should be a function.
 * @returns {plan} Return plan itself.
 * @see {@link https://codepen.io/axui/pen/mdvwQYo|demo @ codepen}
 * @example
 * ax.plan.add('setValues',instance,()=>{});
 */
    add: function(name: any, instance: any, content: T_fn): any  {
        
        let nameType = getDataType(name),
            handle = (str: string) => {
                
                if (!instance.plans.hasOwnProperty(str)) {
                    instance.plans[str] = [];
                }
                
                let newValue = content.toString().replace(/\s/g, '').replace(/\;/g, '').match(/{(\S*)}/),
                    oldValue = instance.plans[str].toString().replace(/\s/g, '').replace(/\;/g, '');
                
                newValue && !oldValue.includes(newValue[1]) ? instance.plans[str].push(content) : null;
            }
        
        this.handle(name, nameType, (item: string) => handle(item));
        return this;
    },
    /**
     * @memberOf plan
     * @description Cancel a plan.
     * @param {string|string[]} name - Plan name.
     * @param {*} instance - Instance object.
     * @param {function} [content] - Plan content.It should be a function.
     * @returns {plan} Return plan itself.
     * @see {@link https://codepen.io/axui/pen/mdvwQYo|demo @ codepen}
     * @example
     * ax.plan.remove('setValues',instance,()=>{});
     */
    remove: function(name: any, instance: any, content?:  T_fn): any {
        let nameType = getDataType(name),
            handle = (str: string) => {
                
                if (!instance.plans.hasOwnProperty(str)) {
                    return console.warn(`The ${str} event is invalid or unusable!`);
                }
                if (!content) {
                    delete instance.plans[str];
                } else {
                    let index = instance.plans[str].findIndex((k: any) => k === content)
                    if (index < 0) {
                        return console.warn(`The ${str} event is not bound!`);
                    }
                    instance.plans[str].splice(index, 1);
                    instance.plans[str].length === 0 ? delete instance.plans[str] : null;
                }
            }
        
        this.handle(name, nameType, (item: string) => handle(item));
        return this;
    },
    /**
     * @memberOf plan
     * @description Implement a plan.
     * @param {string|string[]} name - Plan name.
     * @param {*} instance - Instance object.
     * @param {*} [params] - Plan parameters.0 or multiple.
     * @returns {plan} Return plan itself.
     * @see {@link https://codepen.io/axui/pen/mdvwQYo|demo @ codepen}
     * @example
     * ax.plan.do('setValues',instance,'2026','Los Angeles');
     * <!-- 2026 & Los Angeles are parameters -->
     */
    do:function(name: any, instance: any, ...params: any): any {
        let nameType = getDataType(name),
            handle = (str: string) => {
                
                if (!instance.plans.hasOwnProperty(str)) {
                    return console.warn(`The ${str} event is unregistered or unusable!`);
                }
                instance.plans[str].forEach((k: any) => {
                   k.call(instance, ...params);
                });
            }
        
        this.handle(name, nameType, (item: string) => handle(item));
        return this;
    }
}
export default plan;
