import { Injectable } from '@angular/core' ; import { getJSON , IJson } from './util' ; /**
 * change any object to google object options
 * e.g. [1,2] -> new google.maps.LatLng(1,2);
 */ @ Injectable ( ) export class OptionBuilder { googlizeAllInputs ( definedInputs , userInputs ) { let options = { } ; if ( userInputs . options ) { console . log ( 'userInputs.options .................' , userInputs . options ) ; options = userInputs . options ; if ( ! this . onlyOptionsGiven ( definedInputs , userInputs ) ) { console . error ( 'when "options" are used, other options are ignored' ) ; } } else { definedInputs . forEach ( input => { if ( userInputs [ input ] !== undefined ) { options [ input ] = this . googlize ( userInputs [ input ] , { key : input } ) ; } } ) ; } return options ; } googlizeMultiple ( inputs , options ? ) { options = options || { } ; for ( let key in inputs ) { let val = inputs [ key ] ; if ( typeof val !== 'string' ) { options [ key ] = val ; } else if ( ! ( options [ 'doNotConverStringToNumber' ] && val . match ( /^[0-9]+$/ ) ) ) { options [ key ] = this . googlize ( val , { key : key } ) ; } } return options ; } googlize ( input , options ? ) { options = options || { } ; let output = input ; if ( typeof input === 'string' ) { if ( input === 'false' ) { output = false ; } else if ( input === '0' ) { output = 0 ; } else { output = this . getJSONParsed ( input , options ) || this . getAnyMapObject ( input ) || this . getAnyMapConstant ( input , options ) || this . getDateObject ( input ) || input ; } } if ( options [ 'key' ] ) { let key = < string > options [ 'key' ] ; if ( output instanceof Array ) { if ( key === 'bounds' ) { output = new google . maps . LatLngBounds ( output [ 0 ] , output [ 1 ] ) ; } else if ( key === 'icons' ) { output = this . getMapIcons ( output ) ; } else if ( key === 'position' || key . match ( /^geoFallback/ ) ) { output = this . getLatLng ( output ) ; } } else if ( output instanceof Object ) { if ( key === 'icon' ) { output = this . getMarkerIcon ( output ) ; } else if ( key . match ( /ControlOptions$/ ) ) { output = this . getMapControlOption ( output ) ; } } } delete output [ 'doNotConverStringToNumber' ] ; delete output [ 'key' ] ; return output ; } private getLatLng ( input ) { let output ; if ( input [ 0 ] . constructor === Array ) { output = ( < any [ ] > input ) . map ( ( el ) => new google . maps . LatLng ( el [ 0 ] , el [ 1 ] ) ) ; } else if ( ! isNaN ( parseFloat ( input [ 0 ] ) ) && isFinite ( input [ 0 ] ) ) { output = new google . maps . LatLng ( input [ 0 ] , input [ 1 ] ) ; } return output ; } private getJSONParsed ( input , options ) { let output ; try { output = getJSON ( input ) ; if ( output instanceof Array ) { if ( output [ 0 ] . constructor !== Object ) { output = this . getLatLng ( output ) ; } } else if ( output === Object ( output ) ) { let newOptions = options ; newOptions [ 'doNotConverStringToNumber' ] = true ; output = this . googlizeMultiple ( output , newOptions ) ; } } catch ( e ) { } return output ; } private getAnyMapObject ( input ) { let output ; if ( input . match ( /^[A-Z][a-zA-Z0-9]+\(.*\)$/ ) ) { try { output = Function ( `return new google.maps.${ input };` ) ( ) ; } catch ( e ) { } } return output ; } private getAnyMapConstant ( input , options ) { let output ; if ( input . match ( /^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/ ) ) { try { let matches = input . match ( /^([A-Z][a-zA-Z0-9]+)\.([A-Z]+)$/ ) ; output = google . maps [ matches [ 1 ] ] [ matches [ 2 ] ] ; } catch ( e ) { } } else if ( input . match ( /^[A-Z]+$/ ) ) { try { let capitalizedKey = ( < string > options [ 'key' ] ) . charAt ( 0 ) . toUpperCase ( ) + ( < string > options [ 'key' ] ) . slice ( 1 ) ; output = google . maps [ capitalizedKey ] [ input ] ; } catch ( e ) { } } return output ; } /**
     * streetviewControl, panControl, etc, not a general control
     */ private getMapControlOption ( controlOptions ) { let newControlOptions = controlOptions ; for ( let key in newControlOptions ) { if ( newControlOptions [ key ] ) { let value = newControlOptions [ key ] ; if ( typeof value === 'string' ) { value = ( < string > value ) . toUpperCase ( ) ; } else if ( key === 'mapTypeIds' ) { value = ( < any [ ] > value ) . map ( function ( str ) { if ( str . match ( /^[A-Z]+$/ ) ) { return google . maps . MapTypeId [ str . toUpperCase ( ) ] ; } else { return str ; } } ) ; } if ( key === 'style' ) { let objName = key . replace ( /Options$/ , '' ) + 'Style' ; newControlOptions [ key ] = google . maps [ objName ] [ < any > value ] ; } else if ( key === 'position' ) { newControlOptions [ key ] = google . maps . ControlPosition [ < any > value ] ; } else { newControlOptions [ key ] = value ; } } } return newControlOptions ; } private getDateObject ( input ) { let output ; if ( input . match ( /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/ ) ) { try { output = new Date ( input ) ; } catch ( e ) { } } return output ; } private getMapIcons ( input ) { return input . map ( el => { if ( el . icon . path . match ( /^[A-Z_]+$/ ) ) { el . icon . path = google . maps . SymbolPath [ el . icon . path ] ; } return el ; } ) ; } private getMarkerIcon ( input ) { let output = input ; if ( ( '' + output . path ) . match ( /^[A-Z_]+$/ ) ) { output . path = google . maps . SymbolPath [ output . path ] ; } for ( let key in output ) { let arr = output [ key ] ; if ( key === 'anchor' || key === 'origin' || key === 'labelOrigin' ) { output [ key ] = new google . maps . Point ( arr [ 0 ] , arr [ 1 ] ) ; } else if ( key === 'size' || key === 'scaledSize' ) { output [ key ] = new google . maps . Size ( arr [ 0 ] , arr [ 1 ] ) ; } } return output ; } private onlyOptionsGiven ( definedInputs , userInputs ) { for ( let i = 0 ; i < definedInputs . length ; i ++ ) { let input = definedInputs [ i ] ; if ( input !== 'options' && typeof userInputs [ input ] !== 'undefined' ) { return false ; } } return true ; } }