import { Controller } from "@hotwired/stimulus";
import { GisState } from "../state.js";
import UI from "../ui.js";
import { INIT_ZOOM } from "../gis.js";

const html = String.raw;

export default class extends Controller {
    static targets = [
        'search',
        'results',
        'clear',
        'container',
        'category',
        'technique',
    ];
    
    disableTechnique() {
        this.techniqueTarget.disabled = true;
    }
    disableCategory() {
        this.categoryTarget.disabled = true;
    }
    /**
     * 
     * @param {Event} event 
     */
    async submitSearch(event) {
        event.preventDefault();
        // Re-enable disabled filters, if any
        this.categoryTarget.disabled = false;
        this.techniqueTarget.disabled = false;
        const data = new FormData(event.target);
        const body = {};
        const map = GisState.map;
        const techs = GisState.layers.buildingTechs;
        const techsMarkers = GisState.markers.buildingTechs;

        // Reset search for building techs...
        for (const key of Object.keys(techsMarkers)) {
            map.removeLayer(techsMarkers[key]);
        }

        for (const entry of data.entries()) {
            body[entry[0]] = entry[1];
        }

        const response = await fetch(`${GisState.apiUrl}/search?` + new URLSearchParams(body));
        const results = await response.json(); 

        this.containerTarget.classList.remove('is-hidden');

        if (results.count === 0) {
            // Restore all layer groups
            for (const key of Object.keys(GisState.layers)) {
                map.addLayer(GisState.layers[key]);
            }
            this.resultsTarget.innerHTML = html`
                <p class="has-background-white-bis p-4 mt-0 has-text-centered">
                    Nessun risultato trovato per i parametri di ricerca
                </p>
            `;
        }
        if (results.count) {
            this.#injectResults(results);
            // Reset zoom level after successful search
            map.setZoom(INIT_ZOOM);
            this.#filterMap(results);
            
            // Should technique always be shown after a search?
            for (const key of Object.keys(techsMarkers)) {
                for (const record of results.sites) {
                    // Adjust for non-site records!!
                    if (techsMarkers[key].options.site === record.label
                        && techsMarkers[key].options.label === body.technique)
                        map.addLayer(techsMarkers[key]);
                }
            }
        }
    }

    clearSearch() {
        this.categoryTarget.disabled = false;
        this.techniqueTarget.disabled = false;
        const map = GisState.map;

        // Restore layer groups in map
        for (const key of Object.keys(GisState.layers)) {
            map.addLayer(GisState.layers[key]);
        }

        // Empty result set
        this.resultsTarget.innerHTML = '';
        this.containerTarget.classList.add('is-hidden');
        // Reset map zoom
        map.setZoom(INIT_ZOOM);
    }

    #injectResults(results) {
        /**
         * @type {HTMLOutputElement} output
         */
        const output = this.resultsTarget;
        output.innerHTML = '';

        delete results.count;

        for (const group of Object.keys(results)) {
            if (results[group].length) this.#populateResults(group, results[group], output);
        }
    }
    /**
     * 
     * @param {string} group 
     * @param {Array<Object>} resultGroup 
     * @param {HTMLOutputElement} output 
     */
    #populateResults(group, resultGroup, output) {
        const markers = GisState.markers[group];
        for (const result of resultGroup) {
            let coordinates = '';
            for (let key of Object.keys(markers)) {
                if (markers[key].options.data.label === result.label) {
                    coordinates = key;
                }
            }

            // TODO The group value should be dynamic!!
            const item = html`
                <tr>
                    <td class="pt-4">${result.label}</td>
                    <td>
                        <button class="button is-link"
                            data-controller="marker"
                            data-action="marker#go"
                            data-marker-zoom-param="17"
                            data-marker-coords-value="${coordinates}"
                            data-marker-group-value="${resultGroup}">
                            Vai
                            <span class="ml-1 icon">
                                <i class="fa fa-chevron-right"></i>
                            </span>
                        </button>
                    </td>
                </tr>
            `;

            output.innerHTML += item;
        }
    }
    /**
     * 
     * @param {Object} results 
     */
    #filterMap(results) {
        const map = GisState.map;

        // Remove all layer groups first
        for (const key of Object.keys(GisState.layers)) {
            map.removeLayer(GisState.layers[key]);
        }

        const markers = GisState.markers;

        for (let group of Object.keys(results)) {
            for (let key of Object.keys(markers[group])) {
                // If map has layers from previous search results...
                map.removeLayer(markers[group][key]);
                
                for (const result of results[group]) {
                    if (markers[group][key].options.data.label === result.label) {
                        map.addLayer(markers[group][key]);
                    }
                }
            }
        }
    }
}
