import createEl from '../utils/createEl';
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 optMore from '../options/optMore';
import prefix from '../global/prefix';
class More extends pipe(PubListen, PubUpdate, PubCommon)(PubBase) {
    constructor(elem, options, initial = true) {
        super();
        this.options = {};
        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) {
        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) {
            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) {
        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() {
        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) {
        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, cb) {
        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;
    }
}
More.hostType = 'node';
export default More;
