import { Marker } from '../toubiz-map/data/marker';
import { getMapConstructors } from './static-map-pair-factory';

/**
 * @typedef {object} StaticMap~Marker
 * @property {number} latitude
 * @property {number} longitude
 * @property {string} tour
 * @property {string} iconUrl
 * @property {number} iconWidth
 * @property {number} iconHeight
 */

/**
 * @typedef {object} StaticMap~Options
 * @property {StaticMap~Marker[]} markers
 * @property {string} mapType
 * @property {AbstractMapWithMarkers~Options} [map = {}]
 */

/**
 * Static map: Displays a static map until the user clicks on it at which point a
 * dynamic map is being loaded.
 */
export class StaticMap {

    /**
     * @param {HTMLElement} node
     * @param {StaticMap~Options} settings
     */
    constructor (node, settings) {
        /** @private {HTMLElement} */
        this.node = node;

        /** @private {StaticMap~Options} */
        this.settings = settings;

        const markers = this.getMarkers();
        const picture = this.initializeStaticMap(markers);
        picture.addEventListener('click', async () => {
            this.setNodeSizeToImageSize(picture);
            await this.initializeDynamicMap(markers);
            if (picture.parentNode) {
                picture.parentNode.removeChild(picture);
            }
        });
    }

    /**
     * @private
     * @param {Marker[]} markers
     * @returns {HTMLPictureElement}
     */
    initializeStaticMap(markers) {
        const picture = document.createElement('picture');
        this.node.appendChild(picture);

        const config = this.settings.map || {};
        config.width = this.settings.width;
        config.height = this.settings.height;

        const maps = getMapConstructors(this.settings.mapType);
        const map = new maps.Static(picture, config);
        map.render(markers);

        return picture;
    }

    /**
     * @private
     * @param {Marker[]} markers
     * @returns {Promise<void>}
     */
    async initializeDynamicMap(markers) {
        const maps = getMapConstructors(this.settings.mapType);
        const map = new maps.Dynamic(this.node, this.settings.map || {});
        await map.render(markers);
        map.centerMapOnMarkers(markers);

        if (map.drawTourOntoMap) {
            markers.forEach(marker => {
                if (marker.tour && marker.tour.polygon) {
                    map.drawTourOntoMap(marker);
                }
            });
        }
    }

    /**
     * @private
     * @returns {Marker[]}
     */
    getMarkers() {
        return this.settings.markers.map(data => {
            const marker = new Marker();
            marker.coordinates = {
                latitude: parseFloat(data.latitude),
                longitude: parseFloat(data.longitude),
            };
            if (data.tour) {
                marker.tour = { polygon: JSON.parse(data.tour) };
            }
            if (data.iconUrl) {
                const width = data.iconWidth || 35;
                const height = data.iconHeight || 50;
                marker.style = {
                    width,
                    height,
                    offsetX: width / 2,
                    offsetY: height,
                    iconUrl: data.iconUrl,
                };
            }
            return marker;
        });
    }

    setNodeSizeToImageSize(picture) {
        const rect = picture.getBoundingClientRect();
        this.node.style.width = `${rect.width}px`;
        this.node.style.height = `${rect.height}px`;
    }

}
