/**  
 * @since Last modified: 2024/06/20 22:35:59
 * @class CheckboxesElem
 * @description The custom element : ax-checkboxes .
 * @see {@link https://codepen.io/axui/pen/bGJWLbg|demo @ codepen}
 * @example
 * <ax-checkboxes name="demo" value="book" label="Reading"></ax-checkboxes>;
 */

import { T_el, T_obj } from '../../../types/ax';
import prefix from '../global/prefix';
import classes from '../utils/classes';
import createEl from '../utils/createEl';
import fieldTools from '../utils/fieldTools';
import fileTools from '../utils/fileTools';
import getAttrArr from '../utils/getAttrArr';
import getAttrBool from '../utils/getAttrBool';
import getEl from '../utils/getEl';
import getEls from '../utils/getEls';
import isNull from '../utils/isNull';
import storage from '../utils/storage';
import PlainElem from './PlainElem';

class CheckboxesElem extends PlainElem {
    labelEl: any;
    inputEl: any;
    legendEl: any;
    inputs: any;
    checkAll: any;
    switch: any;
    setValues: any;
    check: any;
    setLabels: any;
    switchType: any;
    switchEvent: any;
    constructor() {
        super();
        
        super.createObs();
        
        this.getRawData();
        
        this.fillWrap(this.propsProxy);

        this.reset = () => {
            for (let k in this.propsRaw) {
                
                k === 'data' ? this.updateInputs(this.propsRaw[k], this.propsRaw) :
                    (this.propsRaw[k] !== null && this.propsRaw[k] !== false) ? this.setAttribute(k, this.propsRaw[k]) : this.removeAttribute(k);
            }
            this.listen({ name: 'reset' });
        }
        
        this.clear = () => {
            this.setAttribute('check', '');
            this.listen({ name: 'clear' });
        }
        
        this.checkAll = () => {
            let vals = this.inputs.map((k: any) => k.propsProxy.value);
            this.setAttribute('check', vals);
            this.listen({ name: 'checkAll', params: [vals] });
        }
        
        this.setValues = (value: string | string[]) => {
            
            let vals = Array.isArray(value) ? value.join(',') : value;
            this.setAttribute('check', vals);
            this.listen({ name: 'check', params: [vals] });
        }
        
        this.setLabels = (label: string | string[]) => {
            
            let lbls = Array.isArray(label) ? label.join(',') : label,
                vals = this.inputs.filter((k: any) => lbls.includes(k.propsProxy.label)).map((k: any) => k.propsProxy.value);
            this.setAttribute('check', vals);
            this.listen({ name: 'check', params: [vals] });
        }
        this.observer.ins.on('set', (data: T_obj) => {
            
            
            data.key !== 'value' && this.initialized && this.updateCache({ [data.key]: data.value });
        });
        this.observer.ins.on('complete', (data: T_obj) => {
            
            if (data.keys.includes('value')) {
                
                this.referSwitch(data.proxy.value);
                
                this.updateCache({ check: data.proxy.value });
                this.listen({ name: 'change', params: [data.proxy.value] });
            }
        });
        
        this.switchEvent = (e: any) => {
            let val = fieldTools.getVals({
                el: e.target,
                parent: this.switch,
                format: 'string',
            });
            
            
            val == '1' ? this.checkAll() : this.clear();
            console.log(val)
        }
    }
    
    static lazyAttrs = ['stor-name'];
    static custAttrs = [
        'class',
        'size', 'name', 'type', 'layout', 'cols', 'check', 'disable', 'data', 'switch', 'wrap-classes', 'item-classes', 'input-classes',
        'on-change', 'on-init', 'on-set', 'on-reset', 'on-clear', 'on-checkall'
    ];
    
    
    
    
    static boolAttrs = ['disabled'];
    
    static get observedAttributes() {
        
        return ['data', ...this.custAttrs, ...this.boolAttrs];
    }
    
    attributeChangedCallback(name: string, oldVal: string, newVal: string) {
        
        
        this.propsProxy[name] = this.getPropVal(CheckboxesElem, name, newVal);

        
        if (name === 'data') {
            
            this.updateInputs(newVal);
        } else if (name === 'disabled') {
            this.setAttribute('disabled', '');
        } else if (['name', 'type', 'size'].includes(name)) {
            this.inputs.forEach((k: any) => {
                k.setAttribute(name, newVal);
            });
        } else if (name === 'check') {
            
            
            if (!newVal) {
                
                this.inputs.forEach((k: any) => {
                    k.check('');
                });
            } else {
                
                let tmp = getAttrArr(newVal);
                this.inputs.forEach((k: any) => {
                    if (tmp.includes(k.propsProxy.value)) {
                        k.check('ed');
                    } else {
                        k.check('');
                    }
                });
            }

        } else if (name === 'disable') {
            
            
            let tmp = getAttrArr(newVal);
            this.inputs.forEach((k: any) => {
                if (tmp.includes(k.propsProxy.value)) {
                    k.setAttribute('disabled', '');
                } else {
                    k.removeAttribute('disabled');
                }
            });
        } else if (name === 'switch') {
            
            this.switch = getEl(`[name="${newVal}"]`);
            
            if (this.switch) {
                
                this.switchType = this.switch.nodeName;
                this.switch.inputs.forEach((k: any) => {
                    
                    k.inputEl.removeEventListener('change', this.switchEvent);
                    k.inputEl.addEventListener('change', this.switchEvent, false);
                });
            }
        }
    }
    
    connectedCallback() {
        
        this.connectedRender();
    }
    
    disconnectedCallback() {
    }
    
    adoptedCallback() {
    }
    getRawData() {
        
        this.getInitPropsRaw(CheckboxesElem);
        
        
        let tmp = this.getAttribute('data') ? getAttrArr(this.getAttribute('data')) : getAttrArr(this.innerHTML.replace(/\n/g, '').trim());
        this.propsRaw.data = this.formatData(tmp);
        this.getInitPropsProxy();
        
        this.innerHTML = '';
    }
    fillWrap(data: T_obj) {
        this.wrapEl = createEl('div', { role: 'wrap' });
        data['wrap-classes'] ? classes.add(this.wrapEl, data['wrap-classes']) : null;
        
        if (data.layout === 'grid') {
            this.wrapEl.classList.add(`${prefix}grid`);
            
            data.cols && this.wrapEl.classList.add(`${prefix}avg-${data.cols}`);
        } else if (data.layout === 'flex') {
            this.wrapEl.classList.add(`${prefix}row`);
        }
        this.updateInputs(data.data, data);
    }
    updateInputs(data: string | any[], host = this.propsProxy) {
        
        this.inputs = [];
        this.wrapEl.innerHTML = '';
        
        let tmp = Array.isArray(data) ? data : getAttrArr(data);
        
        this.formatData(tmp).forEach((k: any) => {
            let parent = createEl('div'),
                input: any = createEl('ax-checkbox', { name: host.name, label: k.label, value: isNull(k.value) ? k.label : k.value, check: k.checked ? 'ed' : '' });
            k.disabled && input.setAttribute('disabled', '');
            host['input-classes'] && classes.add(input, host['input-classes']);
            
            this.inputs.push(input);
            if (host.layout) {
                host.layout === 'flex' && parent.classList.add(`${prefix}flex`);
                host['item-classes'] && classes.add(parent, host['item-classes']);
                parent.appendChild(input);
                this.wrapEl.appendChild(parent);
            } else {
                
                this.wrapEl.appendChild(input);
            }
        });
        
        this.inputs.forEach((k: any) => {
            k.on('change', () => {
                let eds = this.inputs.filter((i: any) => i.propsProxy.check === 'ed').map((o: any) => o.propsProxy.value).join(',');
                
                this.propsProxy.value = eds;
            });
        });

    }
    formatData(data: any) {
        let itemType = typeof data[0];
        if (itemType === 'string') {
            
            return data.map((k: string) => {
                return { label: k, value: k, disabled: false, checked: false }
            });
        } else {
            return data;
        }
    }
    referSwitch(val: string) {
        if (!this.switch) { return this }

        
        if (!val) {
            
            this.switchType === 'AX-CHECKBOXES' ? this.switch.clear() : this.switch.setValues('0');
        } else {
            let tmp = val.split(',').length;
            if (tmp > 0 && tmp < this.inputs.length) {
                this.switch.clear();
                /* this.switch.inputs.forEach((k: any) => {
                    
                    k.propsProxy.value == '1' ? k.setAttribute('check', 'ing') : k.removeAttribute('check')
                }); */
                let tmp = this.switch.inputs.find((k: any) => k.propsProxy.value == '1');
                tmp && tmp.setAttribute('check', 'ing')
            } else {
                
                /* let tmp = this.switch.inputs.find((k: any) => k.propsProxy.value == '1');
                tmp && tmp.setAttribute('check', 'ed') */
                this.switch.setValues('1');
            }
        }
    }
    render() {
        
        this.appendChild(this.wrapEl);
        
    }

}
window.customElements.define("ax-checkboxes", CheckboxesElem);
export default CheckboxesElem;
