/**  
 * @since Last modified: 2024-09-10 11:20:41
 * @class More
 * @description Folding too long text and omittind.
 * @param {*} elem - target element
 * @param {Object} [options] - Parameters 
 * @see {@link https://codepen.io/axui/pen/ZEwvpNL|demo @ codepen}
 * @example
 * ax.More('#id');
 */
import getEl from '../utils/getEl';
import isEmpty from '../utils/isEmpty';
import instance from '../utils/instance';
import breakpoints from '../utils/breakpoints';
import createEl from '../utils/createEl';
import deepClone from '../utils/deepClone';
import purifyHtml from '../utils/purifyHtml';
import PubBase from './PubBase';
import PubListen from './PubListen';
import PubUpdate from './PubUpdate';
import PubCommon from './PubCommon';
import pipe from '../utils/pipe';
import ax from '../ax';
import { T_more } from '../../../types/more';
import { T_fn, T_obj } from '../../../types/ax';
import optMore from '../options/optMore';
import elProps from '../utils/elProps';
import prefix from '../global/prefix';
import alias from '../global/alias';
class More extends pipe(PubListen, PubUpdate, PubCommon)(PubBase) {
    targetEl: any;
    options: T_more = {};
    destroyed: any;
    plans: any;
    storKeys: any;
    storObs: any;
    storTmp: any;
    rawOpts: any;
    intercepted: any;
    button: any;
    content: any;
    folded: any;
    cmptAttrs: any;
    handlers: any;
    html: any;
    pureHtml: any;
    event: any;
    text: any;
    ell: any;
    static hostType = 'node';
    constructor(elem: any, options?: T_more,initial:boolean=true) {
        super();
        this.ready({
            options,
            maps: optMore,
            host: elem,
            component: true,
        });
        /**
        * @name More.content
        * @description Original content. The content that can be filled without html tags.
        * @type string
        */
        this.content = '';
        super.listen({ name: 'ready' });
        initial && this.init() ;
    }
    /**
     * @description Initialization instance.No parameters.
     * @param {fn_cb_init} [cb] - Call back after initialization.
     * @returns {*} Return the instance itself.
     */
    async init(cb?: T_fn): Promise<any> {
        super.listen({ name: 'launch' });
        this.options.b4Init && await this.options.b4Init.call(this);
        /**
        * @name More.folded
        * @description fold state is true or false.
        * @type boolean
        */
        this.folded = this.options.folded;
        this.getPureContent();
        this.targetEl.innerHTML = this.content;
        this.setAttrs();
        if (this.content.length > (this.options.length as number)) {
            this.intercepted = this.content.substring(0, this.options.length) + '...';
            this.button = createEl('i');
            this.targetEl.appendChild(this.button);
            this.toggle(this.folded ? 'fold' : 'unfold');
            this.button.onclick = () => {
                this.folded ? this.toggle('unfold') : this.toggle('fold');
            };
        }
        super.listen({ name: 'init', cb });
        return this;
    }
    /**
    * @callback fn_cb_init
    * @description Execute a function after destroy.
    * @returns null.
    */
    /**
    * @description Set attributes and styles to the target node after initialization.
    * @returns null
    */
    setAttrs() {
        if (!super.isCmpt(this.targetEl)) {
            this.targetEl.classList.add(`${prefix}${this.constructor.name}`);
        }
    }
    /**
    * @description Fold and unfild according to the type.
    * @param {string} type - fold or unfold.
    * @returns null
    */
    toggle(type: string) {
        if (type === 'unfold') {
            this.targetEl.removeChild(this.button.previousSibling);
            this.button.innerHTML = this.options.textUnfold;
            this.button.setAttribute('class', this.options.classUnfold);
            this.button.insertAdjacentHTML('beforeBegin', this.content);
            super.listen({ name: 'unfold' });
            this.folded = false;
        } else if (type === 'fold') {
            this.targetEl.removeChild(this.button.previousSibling);
            this.button.innerHTML = this.options.textFold;
            this.button.setAttribute('class', this.options.classFold);
            this.button.insertAdjacentHTML('beforeBegin', this.intercepted);
            super.listen({ name: 'fold' });
            this.folded = true;
        }
        super.updateCache({ folded: this.folded });
    }
    /**
     * @description Get pure text content and update Content variables.
     * @returns null
     */
    getPureContent(): void {
        if (this.options.content && typeof this.options.content === 'string') {
            this.content = super.getStrFromContent(this.options.content)
        } else {
            this.content = this.rawHtml ? this.rawHtml : this.targetEl.innerHTML;
        }
        this.content = purifyHtml(this.content);
    }
    /**
     * @description Destroy instance.Prohibit use.
     * @param {fn_cb_destroy} cb - Call back after destroy.
     * @returns {*} Return the instance itself
     */
    destroy(cb?: any): any {
        if (this.destroyed) {
            return this;
        }
        this.button.onclick = null;
        super.clearCache();
        this.destroyed = true;
        super.listen({ name: 'destroy', cb });
        return this;
    }
    /**
     * @callback fn_cb_destroy
     * @description Execute a function after destroy.
     * @returns null.
     */
    /**
   * @description Update content.
   * @param {string} text - The text to be updated.It can be a node selector(e.g. #id or .classname) or a pure text.
   * @param {fn_cb_update_content} cb - Call back after update content.
   * @returns {*} Return the instance itself
   */
    updateCont(text: string, cb: Function): any {
        if (this.destroyed) {
            return this;
        }
        this.options.content = text;
        this.init();
        super.updateCache({ content: this.content });
        super.listen({ name: 'updateCont', cb, params: [this.content] });
        return this;
    }
    /**
     * @callback fn_cb_update_content
     * @description Execute a function after update content.
     * @param {string} content - The text to be updated.
     * @returns null.
     */
}
export default More;
