/**
 * Copyright 2020 Google LLC
 *
 * 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 { LatLng , LatLngBounds , LatLngLiteral } from "./common" ; import { encodePath } from "./util" ; import { createSignature } from "@googlemaps/url-signature" ; import { stringify as qs } from "query-string" ; const separator = "|" ; export function latLngToString ( o ) { if ( typeof o === "string" ) { return o ; } else if ( Array . isArray ( o ) && o . length === 2 ) { } else if ( "lat" in o && "lng" in o ) { o = [ o . lat , o . lng ] ; } else if ( "latitude" in o && "longitude" in o ) { o = [ o . latitude , o . longitude ] ; } else { throw new TypeError ( ) ; } return o . map ( ( x ) => { return x . toString ( ) ; } ) . join ( "," ) ; } export function objectToString ( o ) { if ( typeof o === "string" ) { return o ; } else { let keys = Object . keys ( o ) ; keys . sort ( ) ; return keys . map ( ( k ) => k + ":" + o [ k ] ) . join ( separator ) ; } } export function latLngBoundsToString ( latLngBounds ) { if ( typeof latLngBounds === "string" ) { return latLngBounds ; } else { return ( latLngToString ( latLngBounds . southwest ) + separator + latLngToString ( latLngBounds . northeast ) ) ; } } export function toLatLngLiteral ( o ) { if ( typeof o === "string" ) { const parts = o . split ( "," ) . map ( Number ) ; return { lat : parts [ 0 ] , lng : parts [ 1 ] } ; } else if ( Array . isArray ( o ) && o . length === 2 ) { const parts = o . map ( Number ) ; return { lat : parts [ 0 ] , lng : parts [ 1 ] } ; } else if ( "lat" in o && "lng" in o ) { return o ; } else if ( "latitude" in o && "longitude" in o ) { return { lat : o . latitude , lng : o . longitude } ; } else { throw new TypeError ( ) ; } } export function latLngArrayToStringMaybeEncoded ( o ) { if ( typeof o === "string" ) { return o ; } const concatenated = o . map ( latLngToString ) . join ( separator ) ; const encoded = `enc:${ encodePath ( o . map ( toLatLngLiteral ) ) }` ; if ( encoded . length < concatenated . length ) { return encoded ; } return concatenated ; } export type serializerFunction = ( any ) => string | number | boolean ; export type serializerFormat = { [ key ] : serializerFunction ; } ; export function serializer ( format , baseUrl , queryStringOptions = { arrayFormat : "separator" , arrayFormatSeparator : separator , } ) { return ( params ) => { const serializedParams = { ... params } ; Object . keys ( format ) . forEach ( ( key ) => { if ( key in serializedParams ) { serializedParams [ key ] = format [ key ] ( serializedParams [ key ] ) ; } } ) ; if ( "client_id" in serializedParams && "client_secret" in serializedParams ) { return createPremiumPlanQueryString ( serializedParams , queryStringOptions , baseUrl ) ; } return qs ( serializedParams , queryStringOptions ) ; } ; } export function toTimestamp ( o ) { if ( o === "now" ) { return o ; } if ( o instanceof Date ) { return Number ( o ) / 1000 ; } return o ; } export function createPremiumPlanQueryString ( serializedParams , queryStringOptions , baseUrl ) { serializedParams . client = serializedParams . client_id ; const clientSecret = serializedParams . client_secret ; delete serializedParams . client_id ; delete serializedParams . client_secret ; const partialQueryString = qs ( serializedParams , queryStringOptions ) ; const unsignedUrl = `${ baseUrl }?${ partialQueryString }` ; const signature = createSignature ( unsignedUrl , clientSecret ) ; return `${ partialQueryString }&signature=${ signature }` ; }