import { ResultsListController } from '../common/results-list-controller.class';
import { attributeSelector } from '../common/selector-utilities';
import { Marker } from '../toubiz-map/data/marker';
import { extractPrefixedAttributesFromElement } from '@nimius/dom-utility';
import { initializeMap, setupAutomaticClickHandling } from '../toubiz-map/map/map-factory';

const ATTRIBUTE = Object.freeze({
    SPLITSCREEN_ACTIVE_CLASS: 'data-toubiz-results.splitscreen.active-classes',
    SPLITSCREEN_INACTIVE_CLASS: 'data-toubiz-results.splitscreen.inactive-classes',
    SPLITSCREEN_TOGGLE: 'data-toubiz-results.splitscreen.toggle-input',
    SPLITSCREEN_MARKER: 'data-toubiz-results.splitscreen.marker',
    SPLITSCREEN_MAP_CONTAINER: 'data-toubiz-results.splitscreen.map-container',
    SPLITSCREEN_SCROLL_CONTAINER: 'data-toubiz-results.splitscreen.scroll-container',
});

/**
 * Controls pagination and list rendering on toubiz poi results view.
 */
export default class ToubizPoiResultsListController extends ResultsListController {

    onInitialize () {
        /** @private {boolean} */
        this.splitScreen = false;

        /** @private {Marker[]} */
        this.mapMarkers = [];

        /** @private {AbstractMapWithMarkers} */
        this.map = null;

        /** @private {number} */
        this.lastSplitScreenToggle = window.performance.now();

        for (const input of document.querySelectorAll(attributeSelector(ATTRIBUTE.SPLITSCREEN_TOGGLE))) {
            // Set to false initially because in firefox it stays checked after reload
            input.checked = false;
            input.addEventListener('change', event => {
                const enableSplitScreen = event.target.checked || false;
                this.toggleSplitScreen(enableSplitScreen);
            });
        }

        this.toggleSplitScreen(false);
    }

    async onReinitialize () {
        this.mapMarkers = [];
        for (const coord of this.container.querySelectorAll(attributeSelector(ATTRIBUTE.SPLITSCREEN_MARKER))) {
            const data = extractPrefixedAttributesFromElement(coord, `${ATTRIBUTE.SPLITSCREEN_MARKER}.`);
            const marker = new Marker();
            marker.coordinates = {
                latitude: parseFloat(data.latitude),
                longitude: parseFloat(data.longitude),
            };
            marker.style = {
                iconUrl: data.iconUrl,
                height: 50,
                width: 35,
                offsetX: 25,
                offsetY: 35,
                iconSize: 19,
            };
            marker.style.iconUrl = data.iconUrl;
            marker.contentRenderer = () => coord.innerHTML;

            if (data.tour) {
                marker.tour = { polygon: data.tour };
            }

            this.mapMarkers.push(marker);
        }

        if (this.map) {
            await this.map.render(this.mapMarkers);
            await this.map.centerMapOnMarkers(this.mapMarkers);
        }
    }

    async onReload () {
        this.mapMarkers = [];
        if (this.map) {
            await this.map.render(this.mapMarkers);
            if (this.map.closeInfoWindow) {
                this.map.closeInfoWindow();
            }
            if (this.map.clearTours) {
                this.map.clearTours();
            }
        }

        const container = document.querySelector(attributeSelector(ATTRIBUTE.SPLITSCREEN_SCROLL_CONTAINER));
        if (container) {
            container.scrollTo({ top: 0, behavior: 'smooth' });
        }
    }

    formReloadOptions (form) {
        const options = super.formReloadOptions(form);

        const formDataTransform = options.formDataTransform;
        options.formDataTransform = data => {
            data.append('layout', this.splitScreen ? 'list' : 'teaser');
            if (formDataTransform) {
                data = formDataTransform(data);
            }
            return data;
        };

        return options;
    }

    async toggleSplitScreen(status = null) {
        const before = this.splitScreen;
        if (status === null) {
            status = !this.splitScreen;
        }
        this.splitScreen = status;

        if (this.splitScreen) {
            this.addClassesToAllChildren(ATTRIBUTE.SPLITSCREEN_ACTIVE_CLASS);
            this.removeClassesFromAllChildren(ATTRIBUTE.SPLITSCREEN_INACTIVE_CLASS);
            document.querySelector('html').classList.add('has-overlay');
            if (!this.map) {
                this.map = await this.initializeMap();
            }
        } else {
            this.addClassesToAllChildren(ATTRIBUTE.SPLITSCREEN_INACTIVE_CLASS);
            this.removeClassesFromAllChildren(ATTRIBUTE.SPLITSCREEN_ACTIVE_CLASS);
            document.querySelector('html').classList.remove('has-overlay');
        }

        if (before !== this.splitScreen) {
            this.lastSplitScreenToggle = window.performance.now();
            this.formReload.reload();
        }
    }

    shouldPaginationBeResetBeforeLoadingContent (lastKnownPage, currentPage) {
        if ((window.performance.now() - this.lastSplitScreenToggle) < 1000) {
            return false;
        }
        return super.shouldPaginationBeResetBeforeLoadingContent(lastKnownPage, currentPage);
    }

    async initializeMap() {
        const mapContainer = document.querySelector(attributeSelector(ATTRIBUTE.SPLITSCREEN_MAP_CONTAINER));
        const mapConfig = extractPrefixedAttributesFromElement(mapContainer, 'data-toubiz-results.splitscreen.');

        mapConfig.mapType = mapConfig.mapType || 'osm';
        mapConfig.map = mapConfig.map || {};
        mapConfig.map.center = mapConfig.map.center || { latitude: 0, longitude: 0 };
        mapConfig.map.zoom = mapConfig.map.zoom || 60;
        mapConfig.map.clustering = mapConfig.map.clustering || {};
        mapConfig.map.clustering.color = mapConfig.map.clustering.color || 'white';
        mapConfig.map.clustering.backgroundColor = mapConfig.map.clustering.backgroundColor || 'tomato';

        const map = await initializeMap(mapConfig.mapType, mapContainer, mapConfig.map);
        setupAutomaticClickHandling(map);
        return map;
    }


    addClassesToAllChildren(attributeName) {
        for (const child of document.querySelectorAll(attributeSelector(attributeName))) {
            child.getAttribute(attributeName)
                .split(' ')
                .forEach(clss => child.classList.add(clss));
        }
    }

    removeClassesFromAllChildren(attributeName) {
        for (const child of document.querySelectorAll(attributeSelector(attributeName))) {
            child.getAttribute(attributeName)
                .split(' ')
                .forEach(clss => child.classList.remove(clss));
        }
    }


}
