import { Importer } from './abstract-importer.class';
import { Marker } from '../marker';
import { FilterItem } from '../filter-item';
import { notifyErrorIfInDevelopment } from '../../../common/development-error-notification';

export class ApiImporter extends Importer {

    /**
     * @returns {Promise}
     */
    import() {
        const promises = [];
        if (this.settings.markerUrl) {
            promises.push(this.importMarkers(this.settings.markerUrl));
        }
        if (this.settings.filterItemUrl) {
            promises.push(this.importFilterItems(this.settings.filterItemUrl));
        }
        return Promise.all(promises);
    }

    async importMarkers(url) {
        const firstPageResponse = await this.importMarkerPage(url, 1);
        const lastPage = firstPageResponse._pagination.pages;
        if (lastPage === 1) {
            return;
        }

        const batchSize = 10;
        let promises = [];
        for (let i = 2; i <= lastPage; i++) {
            promises.push(this.importMarkerPage(url, i));
            if (promises.length > batchSize) {
                // eslint-disable-next-line no-await-in-loop
                await Promise.all(promises);
                promises = [];
            }
        }

        await Promise.all(promises);
    }

    async importMarkerPage(url, page) {
        const body = await this.sendRequest(`${url}&page=${page}`);
        const markers = Object.values(body.payload).map(data => this.dataToMarker(data));
        this.source.addMarkers(markers);
        return body;
    }

    async importFilterItems(url) {
        const body = await this.sendRequest(url);
        const items = Object.values(body).map(item => this.dataToFilterItem(item));
        this.source.addFilterItems(items);
    }

    async sendRequest(url) {
        const response = await fetch(url, { credentials: 'same-origin' });
        const body = await response.json();
        if (response.status !== 200 || body.error) {
            if (body.error) {
                const trace = body.error.trace;
                delete body.error.trace;
                console.error(body.error);
                // eslint-disable-next-line no-console
                console.table(trace);
                notifyErrorIfInDevelopment(body.error);
            }
            throw new Error(`Requesting ${url} failed: ${response.statusText}`);
        }
        return body;
    }

    dataToFilterItem(data, parent = null) {
        const filterItem = new FilterItem();
        filterItem.title = data.title;
        filterItem.path = data.path;
        filterItem.style = data.style;
        filterItem.overwriteMarkerStyles = !!data.overwriteMarkerStyles;
        filterItem.parent = parent;
        filterItem.openByDefault = !!data.openByDefault;
        filterItem.children = Object.values(data.children).map(child => this.dataToFilterItem(child, filterItem));

        if (data.id && window.location.hash.indexOf(data.id) !== -1) {
            filterItem.forceOpen = true;
        }

        return filterItem;
    }

    dataToMarker(data) {
        const marker = new Marker(data.id);

        if (data.paths) {
            marker.paths = data.paths;
        } else if (data.path) {
            marker.paths = [ data.path ];
        }
        marker.title = data.title || '';
        marker.description = data.description || '';
        marker.categoryTitle = data.categoryTitle || '';
        marker.description = data.description || '';
        marker.image = data.image || null;
        marker.style = data.defaultStyle || {};
        marker.defaultStyle = data.defaultStyle || {};
        marker.coordinates = data.coordinates || { latitude: 0, longitude: 0 };
        marker.tour = data.tour || null;
        marker.outdoorActiveTrackingId = data.outdoorActiveTrackingId || null;
        marker.url = data.url || null;
        marker.urlTarget = data.urlTarget || null;
        marker.detailApiEndpoints = data.detailApiEndpoints || {};
        marker.id = data.id;
        marker.hideMoreLink = data.hideMoreLink || false;
        marker.moreLinkLabel = data.moreLinkLabel || '';

        if (data.id && this.settings.highlightMarker && window.location.hash.indexOf(data.id) !== -1) {
            marker.highlightIcon = this.settings.highlightMarker;
        }

        return marker;
    }

}
