/* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
/* eslint no-prototype-builtins: 0 */
"use strict";
const cm = require("./common.js");

/**
 * geocode an address
 * @alias hm:geocode
 * @param address {string}  address as string
 * @param opt {object}  optional additional parameter, for instance {additionaldata:"IncludeShapeLevel,city"}
 * @returns  {Promise}   {coord,body}. coord is geocode as \[lat,lng\]. body is full json answer
 * 
 * @example
 * ```js
 * const res = await hm.geocode("avenue des chaps elysees, paris");
 * console.log (res.coord);
 * ```
 */
function geocode(address, opt) {

    const settings = cm.addCredentials({
        searchText: address
    }, opt);

    if (settings.locationId)
        delete settings.searchText;

    const url = cm.buildUrl("geocoder", "api.here.com/6.2/geocode.json");
    const that = this;
    const throttling = {
        rpsMode: "gc",
        rps: that._rps,
        concurrent: that._concurrent,
    };
    return cm.hereRestThrottle(url, settings, null, throttling)
        .then(res => {

            if (res.body.Response.View.length == 0) {
                let e = new Error("Geocode Address not found: " + address); // e.message
                throw (e);
            }

            var location = res.body.Response.View[0].Result[0].Location;
            let coord = null;
            if (location.NavigationPosition.hasOwnProperty("Latitude"))
                coord = [location.NavigationPosition.Latitude, location.NavigationPosition.Longitude];
            if (!coord && location.NavigationPosition[0].hasOwnProperty("Latitude"))
                coord = [location.NavigationPosition[0].Latitude, location.NavigationPosition[0].Longitude];
            if (!coord && location.DisplayPosition.hasOwnProperty("Latitude"))
                coord = [location.DisplayPosition.Latitude, location.DisplayPosition.Longitude];
            if (!coord && location.DisplayPosition[0].hasOwnProperty("Latitude"))
                coord = [location.DisplayPosition[0].Latitude, location.DisplayPosition[0].Longitude];


            return {
                coord: coord,
                body: res.body
            };
        });
}


/**
 * reverse geocode a coordinate
 * @alias hm:reverseGeocode
 * @param coord {Coord}  - coord \[lat,lng\] to reverse-geocode
 * @returns  {Promise} returns { location:object, address:object, body:object}. 
 */
function reverseGeocode(coord) {

    const settings = cm.addCredentials({
        mode: "retrieveAddresses",
        prox: coord[0] + "," + coord[1]
    });

    const url = cm.buildUrl("reverse.geocoder", "api.here.com/6.2/reversegeocode.json");
    const that = this;
    const throttling = {
        rpsMode: "rgc",
        rps: that._rps,
        concurrent: that._concurrent,
    };
    return cm.hereRestThrottle(url, settings, null, throttling)
        .then(res => {
            // res.body, res.headers, res.status
            var location = res.body.Response.View[0].Result[0].Location;
            return ({
                location: location,
                address: location.Address,
                body: res.body
            });
        });
}


/**
 * reverse geocode a coordinate. Can centered on a location or within a bounding box
 * @alias hm:geocoderAutocomplete
 * @param opt {Object}  - {query, bb or center} 
 * @param opt.search - {String} text to search
 * @param opt.center - {array} [lat,lng]
 * @param opt.bb {object} - {latm,latM,lngm,lngM}
 * @returns  {Promise} returns [{},{}] 
 */
function geocoderAutoComplete(opt) {

    const settings = cm.addCredentials(opt);

    if (settings.search) {
        settings.query = settings.search;
        delete settings.search;
    }
    if (settings.bb) {
        const bb = settings.bb;
        settings.mapview = bb.latM + "," + bb.lngm + ";" + bb.latm + "," + bb.lngM;
        delete settings.bb;
    }
    if (settings.center) {
        settings.prox = settings.center[0] + "," + settings.center[1];
        delete settings.center;
    }

    const url = cm.buildUrl("autocomplete.geocoder", "api.here.com/6.2/suggest.json");
    const throttling = {
        rpsMode: "gc",
        rps: 100,
        concurrent: 10,
    };

    return cm.hereRestThrottle(url, settings, null, throttling)
        .then(res => {
            return res.body.suggestions;
        });

}


module.exports = {
    geocode: geocode,
    reverseGeocode: reverseGeocode,
    geocoderAutoComplete: geocoderAutoComplete
};