if(!app.helpers) app.helpers = {}
/**
 * Mixing add-in methods to your view instance.
 * All of this should not be a helper, but inherited this from WindozDomContent, but not my framework anymore.
 * @category MyEic
 */
app.helpers.activeAttributes = {

    /**
     * setupTriggers adds all click (data-trigger) and change (data-change) handlers.
     * handlers should have the signatue : onXyz(component, event), will spit a warning if the handler doesn't exist.
     * setupTriggers is re-entrant: it can be called again after refreshing part of the view
     * @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) )
     */
    setupTriggers(components){ // Should inherit this from WindozDomContent, but not my framework anymore.
        for(let component of components.filter(component => component.el.hasAttribute('data-trigger'))) {
            if(typeof this[component.el.dataset.trigger] !== 'function') {
                console.warn(`data-trigger without corresponding method : ${component.el.dataset.trigger}`)
                continue
            }
            component.click = this[component.el.dataset.trigger].bind(this, component)
        }
        for(let component of components.filter(component => component.el.hasAttribute('data-change'))) {
            if(typeof this[component.el.dataset.change] !== 'function') {
                console.warn(`data-change without corresponding method : ${component.el.dataset.trigger}`)
                continue
            }
            component.el.addEventListener("change",this[component.el.dataset.change].bind(this, component))
            if(component.el.type=='text') component.el.addEventListener("keyup",this[component.el.dataset.change].bind(this, component))
        }
    },

    /**
     * setupRefs will populate :
     * => this.components: an attribute 'data-ref="toto"' will create the reference this.components.toto to the EICUI component
     * => this.outputs: an attribute 'data-output="titi"' will create the reference this.outputs.toto to the dom node (used by this.output() )
     * => this.asyncComponents: an attribute 'data-async="tintin"' will create the reference this.asyncComponents.tintin (used by  setAsyncLoading() )
     * => this.asyncElements: an attribute 'data-async="haddock"' will create the reference this.asyncElements.haddock (used by  setAsyncLoading() )
     * setupRefs is re-entrant: it can be called again after refreshing part of the view
     * @param {eicui-components []} components : the view's components (usually result of ui.eicfy(this.el) )
     */
    setupRefs(components){ 
        if(!this.components) this.components = {}
        for(let component of components.filter(component => component.el.hasAttribute('data-ref'))) {
            this.components[component.el.dataset.ref] = component
        }
        if(!this.asyncComponents) this.asyncComponents = {}
        for(let component of components.filter(component => component.el.hasAttribute('data-async'))) {
            this.asyncComponents[component.el.dataset.async] = component
        }
        
        if(!this.asyncElements) this.asyncElements = {}
        for(let el of this.el.querySelectorAll('[data-async]')) {
            if('eicuiId' in el.dataset) continue
            this.asyncElements[el.dataset.async] = el
        }    

        if(!this.outputs) this.outputs = {}
        for(let el of this.el.querySelectorAll('[data-output]')) {
            this.outputs[el.dataset.output] = el
        }        
    },

    /**
     * output (singular) : this.output('mydiv', '<p>Some markup</p>') places markup in a data-output node
     * @param {*} name 
     * @param {*} markup 
     */
    output(name, markup){ 
        if(name in this.outputs) this.outputs[name].innerHTML = markup 
        else console.warn(`Output ${name} not found !`)
    },

    /**
     * setAsyncLoading Turns on all or some of the loaders
     * @param {boolean} value : true to show loading, false to hide
     * @param {string[]} names : (optional) array of names to show/hide, (names given via the data-async attributes)
     * If no names given, will show/hide all asyncs of the view
     * Small counter so it can handle several async requests which are overlapping and using on the same loader.
     * Ex1 overlapping completion: loader=true & REQ1-start, loader=true & REQ2-start, REQ1-end & loader=false, REQ2-end & loader=false ]
     * Ex2 inverted completion:    loader=true & REQ1-start, loader=true & REQ2-start, REQ2-end & loader=false, REQ1-end & loader=false ]
     */
    setAsyncLoading(value, names=null){
        if(!this.asyncComponents) this.asyncComponents = {}
        if(!this.asyncComponentsCnt) this.asyncComponentsCnt = {}
        if(!names) names = [ ...Object.keys(this.asyncComponents), ...Object.keys(this.asyncElements)]
        for(let name of names){
            if(name in this.asyncComponentsCnt){ this.asyncComponentsCnt[name] = value ? this.asyncComponentsCnt[name]+1 : this.asyncComponentsCnt[name]-1 } 
            else { this.asyncComponentsCnt[name] = value ? 1 : 0 }

            if(name in this.asyncComponents) this.asyncComponents[name].loading = (this.asyncComponentsCnt[name]>0)
            if(name in this.asyncElements) {
                const el = this.asyncElements[name].querySelector('.icon-spinner.spin')
                if(el) el.remove()
                if((this.asyncComponentsCnt[name]>0)){
                    this.asyncElements[name].prepend(Object.assign(document.createElement('div'), 
                        { className: 'icon-spinner spin', style: 'width:1em;height:1em;margin:1em;position: absolute;z-index: 9999;' }))
                }
            }
        } 
    },

    /**
     * Manage spin loader
     * @param {*} element 
     * @param {*} loadingText 
     * @returns 
     */
    showLoading(element, loadingText = '<i class="icon-spinner spin"></i>') {
        if (!element) return
        element.classList.add('loading')
        if (element.tagName === 'BUTTON' || element.type === 'button') {
            element.disabled = true
            element.setAttribute('data-original-content', element.innerHTML);
            element.innerHTML = loadingText;
        } else if (element.hasAttribute('contenteditable')) {
            element.setAttribute('data-original-content', element.innerHTML);
            element.innerHTML = `<span class="loader-placeholder">${loadingText}</span>`
            element.setAttribute('contenteditable', 'false')
        }
    },

    hideLoading(element, defaultIcon = null) {
        if (!element) return;
        element.classList.remove('loading')
        if (element.tagName === 'BUTTON' || element.type === 'button') {
            element.disabled = false;
            element.innerHTML = element.getAttribute('data-original-content') || defaultIcon || ''
        } else if (element.hasAttribute('contenteditable')) {
            element.innerHTML = element.getAttribute('data-original-content') || ''
            element.setAttribute('contenteditable', 'true')
        }
    },

}
