/*
 * Copyright 2019-present Open Networking Foundation
 *
 * Licensed 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 {LogService} from '../log.service';

const LONGITUDE_EXTENT = 180;
const LATITUDE_EXTENT = 75;
const GRID_EXTENT_X = 2000;
const GRID_EXTENT_Y = 1000;
const GRID_DIAGONAL = 2236; // 2236 is the length of the diagonal of the 2000x1000 box
const GRID_CENTRE_X = 500;
const GRID_CENTRE_Y = 500;


/**
 * A model of the map bounds bottom left to top right in lat and long
 */
export interface MapBounds {
    lngMin: number;
    latMin: number;
    lngMax: number;
    latMax: number;
}

/**
 * model of the topo2CurrentRegion Loc part of the MetaUi below
 */
export interface LocMeta {
    lng: number;
    lat: number;
}

/**
 * model of the topo2CurrentRegion MetaUi from Device below
 */
export interface MetaUi {
    equivLoc: LocMeta;
    x: number;
    y: number;
}

/**
 * Model of the Zoom preferences
 */
export interface TopoZoomPrefs {
    tx: number;
    ty: number;
    sc: number;
}

/**
 * Utility class with static functions for scaling maps
 *
 * This is left as a class, so that the functions are loaded only as needed
 */
export class ZoomUtils {
    static convertGeoToCanvas(location: LocMeta ): MetaUi {
        const calcX = (LONGITUDE_EXTENT + location.lng) / (LONGITUDE_EXTENT * 2) * GRID_EXTENT_X - GRID_CENTRE_X;
        const calcY = (LATITUDE_EXTENT - location.lat) / (LATITUDE_EXTENT * 2) * GRID_EXTENT_Y;
        return <MetaUi>{
            x: calcX,
            y: calcY,
            equivLoc: {
                lat: location.lat,
                lng: location.lng
            }
        };
    }

    static convertXYtoGeo(x: number, y: number): MetaUi {
        const calcLong: number = (x + GRID_CENTRE_X) * 2 * LONGITUDE_EXTENT / GRID_EXTENT_X - LONGITUDE_EXTENT;
        const calcLat: number = -(y * 2 * LATITUDE_EXTENT / GRID_EXTENT_Y - LATITUDE_EXTENT);
        return <MetaUi>{
            x: x,
            y: y,
            equivLoc: <LocMeta>{
                lat: (calcLat === -0) ? 0 : calcLat,
                lng: calcLong
            }
        };
    }

    /**
     * This converts the bounds of a map loaded from a TopoGson file that has been
     * converted in to a GEOJson format by d3
     *
     * The bounds are in latitude and longitude from bottom left (min) to top right (max)
     *
     * First they are converted in to SVG viewbox coordinates 0,0 top left 1000x1000
     *
     * The the zoom level is calculated by scaling to the grid diagonal
     *
     * Finally the translation is calculated by applying the zoom first, and then
     * translating on the zoomed coordinate system
     * @param mapBounds - the bounding box of the chosen map in lat and long
     * @param log The LogService
     */
static convertBoundsToZoomLevel(mapBounds: MapBounds, log?: LogService): TopoZoomPrefs {

        const min: MetaUi = this.convertGeoToCanvas(<LocMeta>{
            lng: mapBounds.lngMin,
            lat: mapBounds.latMin
        });

        const max: MetaUi = this.convertGeoToCanvas(<LocMeta>{
            lng: mapBounds.lngMax,
            lat: mapBounds.latMax
        });

        const diagonal = Math.sqrt(Math.pow(max.x - min.x, 2) + Math.pow(max.y - min.y, 2));
        const centreX = (max.x - min.x) / 2 + min.x;
        const centreY = (max.y - min.y) / 2 + min.y;
        // Zoom works from the top left of the 1000x1000 viewbox
        // The scale is applied first and then the translate is on the scaled coordinates
        const zoomscale = 0.5 * GRID_DIAGONAL / ((diagonal < 100) ? 100 : diagonal); // Don't divide by zero
        const zoomx = -centreX * zoomscale + GRID_CENTRE_X;
        const zoomy = -centreY * zoomscale + GRID_CENTRE_Y;

        // log.debug('MapBounds', mapBounds, 'XYMin', min, 'XYMax', max, 'Diag', diagonal,
        //     'Centre', centreX, centreY, 'translate', zoomx, zoomy, 'Scale', zoomscale);

        return <TopoZoomPrefs>{tx: zoomx, ty: zoomy, sc: zoomscale};
    }
}
