/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


import { each, isString, createHashMap } from 'zrender/src/core/util';
import parseGeoJson from './parseGeoJson';
// Built-in GEO fixer.
import fixNanhai from './fix/nanhai';
import fixTextCoord from './fix/textCoord';
import fixGeoCoord from './fix/geoCoord';
import fixDiaoyuIsland from './fix/diaoyuIsland';
import BoundingRect from 'zrender/src/core/BoundingRect';
import { GeoJSONRegion } from './Region';
import { GeoJSON, GeoJSONCompressed, GeoJSONSourceInput, GeoResource, GeoSpecialAreas, NameMap } from './geoTypes';


const DEFAULT_NAME_PROPERTY = 'name' as const;

export class GeoJSONResource implements GeoResource {

    readonly type = 'geoJSON';
    private _geoJSON: GeoJSON | GeoJSONCompressed;
    private _specialAreas: GeoSpecialAreas;
    private _mapName: string;

    private _parsedMap = createHashMap<{
        regions: GeoJSONRegion[];
        boundingRect: BoundingRect;
    }, string>();

    constructor(
        mapName: string,
        geoJSON: GeoJSONSourceInput,
        specialAreas: GeoSpecialAreas
    ) {
        this._mapName = mapName;
        this._specialAreas = specialAreas;

        // PENDING: delay the parse to the first usage to rapid up the FMP?
        this._geoJSON = parseInput(geoJSON);
    }

    /**
     * @param nameMap can be null/undefined
     * @param nameProperty can be null/undefined
     */
    load(nameMap: NameMap, nameProperty: string) {

        nameProperty = nameProperty || DEFAULT_NAME_PROPERTY;

        let parsed = this._parsedMap.get(nameProperty);
        if (!parsed) {
            const rawRegions = this._parseToRegions(nameProperty);
            parsed = this._parsedMap.set(nameProperty, {
                regions: rawRegions,
                boundingRect: calculateBoundingRect(rawRegions)
            });
        }

        const regionsMap = createHashMap<GeoJSONRegion>();

        const finalRegions: GeoJSONRegion[] = [];
        each(parsed.regions, function (region) {
            let regionName = region.name;

            // Try use the alias in geoNameMap
            if (nameMap && nameMap.hasOwnProperty(regionName)) {
                region = region.cloneShallow(regionName = nameMap[regionName]);
            }

            finalRegions.push(region);
            regionsMap.set(regionName, region);
        });

        return {
            regions: finalRegions,
            boundingRect: parsed.boundingRect || new BoundingRect(0, 0, 0, 0),
            regionsMap: regionsMap
        };
    }

    private _parseToRegions(nameProperty: string): GeoJSONRegion[] {
        const mapName = this._mapName;
        const geoJSON = this._geoJSON;
        let rawRegions;

        // https://jsperf.com/try-catch-performance-overhead
        try {
            rawRegions = geoJSON ? parseGeoJson(geoJSON, nameProperty) : [];
        }
        catch (e) {
            throw new Error('Invalid geoJson format\n' + e.message);
        }

        fixNanhai(mapName, rawRegions);

        each(rawRegions, function (region) {
            const regionName = region.name;

            fixTextCoord(mapName, region);
            fixGeoCoord(mapName, region);
            fixDiaoyuIsland(mapName, region);

            // Some area like Alaska in USA map needs to be tansformed
            // to look better
            const specialArea = this._specialAreas && this._specialAreas[regionName];
            if (specialArea) {
                region.transformTo(
                    specialArea.left, specialArea.top, specialArea.width, specialArea.height
                );
            }
        }, this);

        return rawRegions;
    }

    /**
     * Only for exporting to users.
     * **MUST NOT** used internally.
     */
    getMapForUser(): {
        // backward compat.
        geoJson: GeoJSON | GeoJSONCompressed;
        geoJSON: GeoJSON | GeoJSONCompressed;
        specialAreas: GeoSpecialAreas;
    } {
        return {
            // For backward compatibility, use geoJson
            // PENDING: it has been returning them without clone.
            // do we need to avoid outsite modification?
            geoJson: this._geoJSON,
            geoJSON: this._geoJSON,
            specialAreas: this._specialAreas
        };
    }

}

function calculateBoundingRect(regions: GeoJSONRegion[]): BoundingRect {
    let rect;
    for (let i = 0; i < regions.length; i++) {
        const regionRect = regions[i].getBoundingRect();
        rect = rect || regionRect.clone();
        rect.union(regionRect);
    }
    return rect;
}

function parseInput(source: GeoJSONSourceInput): GeoJSON | GeoJSONCompressed {
    return !isString(source)
        ? source
        : (typeof JSON !== 'undefined' && JSON.parse)
        ? JSON.parse(source)
        : (new Function('return (' + source + ');'))();
}
