class DropDown {

    constructor( api_call = '', container_selector, valueField = 'slug', labelField = 'name') {
        
        this.container = document.querySelector( container_selector );

        this.valueField = valueField;
        this.labelField = labelField;

        this.api_call = api_call;

        this.dependencies = [];

        this.populate = this.populate.bind( this );
        this.value    = this.value.bind( this );
    }

    empty() {

        this.container.innerHTML = '';
        this.add('', '-- scegli --');
    }
    
    dependsOn( valueField, dropdown ) {

        /// aggiunge la dipendenza dalla dropdown
        this.dependencies.push( { valueField , dropdown } );
        
        /// crea il trigger in base ai cambiamenti sulla dipendenza
        dropdown.container.addEventListener( 'change', this.populate );
    }

    value() {
        return this.container.value;
    }

    /**
     * Ritorna il campo payload associato all'elemento selezionato
     * 
     * @returns object
     */
    payload() {
        
        if( this.container.selectedOptions.length === 0 ) return {};
        
        return JSON.parse( decodeURIComponent( this.container.selectedOptions[0].dataset['payload'] ) );
    }
    
    fetchData() {
        
        let api_call = this.dependencies.length ? this.getApiCallWithDependencyValues() : this.api_call;

        let data = fetch( `/wp-json/api/v1/proxy/${api_call}/` )
        .then( response => response.json() )
        .then( data => {

            let options = data ? data : [];

            // Bisogna controllare perché questa conversione è necessaria
            if ( !Array.isArray(options) ) { 

                options = Object.keys(options).map( key => options[key] );
            }

            return options;
        });

        return data;
    }

    async populate(data = []) {

        /// rimuove tutti gli elementi correnti
        this.empty();
        
        if(this.api_call !== ''){
            data = await this.fetchData();
        }
        
        data.forEach( element => this.add( element[ this.valueField ], element[ this.labelField ], element ) );
    }

    getApiCallWithDependencyValues() {

        if( this.missingDependency() ) return '';

        return this.dependencies.reduce( (api_call, dependency) => api_call.replace( dependency.valueField, dependency.dropdown.value() ), this.api_call ); 
    }

    missingDependency() {
    
        return this.dependencies.some( dependency => !dependency.dropdown.value() );
    }

    add( value, label, payload = '') {

        let option = `<option value="${ value }" data-payload=${ this.payloadToString(payload) }>${ label }</option>`;
        
        this.container.insertAdjacentHTML( 'beforeend', option );
    }

    payloadToString( payload ) {

        return encodeURIComponent( JSON.stringify( payload ) );
    }

    stringToPayload( string ) {

        return JSON.parse( decodeURIComponent( string ) );
    }
}
    
class Form {

    constructor( apiBase = `https://links-master-book.blazemedia.it/wp-json/api/v1`) {

        this.fields = {};

        this.apiBase = apiBase;

        this.domain  = window.location.host.split('.').slice(-2).join('.');

        this.submitConditions = [];

        this.initFields();

        this.submit = this.submit.bind( this );

        document.getElementById('submit').addEventListener( 'click', this.submit );
    }

    setSubmitCondition( callback ) {

        this.submitConditions.push( callback );
    }

    addDropdown( name, api_call, selector, valueField = 'slug', labelField = 'name', data = []){ 

        this.fields[name] = new DropDown( api_call, selector, valueField, labelField );
        
        this.fields[name].populate(data);
    }

    initFields() {
        throw 'method to be declared in derivates';
    }

    submit() {
        throw 'method to be declared in derivates';
    }
}
