/*!
  Copyright (c) 2010, Grenland Web AS. All rights reserved.

  Example with input hidden variables:

  <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true&amp;language=no"></script>
  <script language="javascript" type="text/javascript" src="javascript/gwgmarkermap.js"></script>

  <div id="google-canvas" style="position: relative; height: 280px;">­</div>
  <script type="text/javascript" language="javascript">
  <!--
    gwGMarkerMap.initialize( 'google-canvas' );
    gwGMarkerMap.setMarker( '5090', true ); // show or hide the marker.

    gwGMarkerMap.addAllMarkers(); // for use with input variables.
    gwGMarkerMap.zoomToFit();
  // -->
  </script>

  <input type="hidden" name="gwGMarkerMapIDList[]" value="5090" />
  <input type="hidden" name="gwGMarkerMapLat['5090']" id="gwGMarkerMapLat-5090" value="9.26" />
  <input type="hidden" name="gwGMarkerMapLng['5090']" id="gwGMarkerMapLng-5090" value="0.39" />
  <input type="hidden" name="gwGMarkerMapName['5090']" id="gwGMarkerMapName-5090" value="Welcome to this company." />
  <input type="hidden" name="gwGMarkerMapURL['5090']" id="gwGMarkerMapURL-5090" value="/content/view/full/5090" />
  <input type="hidden" name="gwGMarkerMapContent['5090']" id="gwGMarkerMapURL-5090" value="More detailed information" />

  <input type="checkbox" value="1" name="gwGMarkerMapShowInMap['5090']"
         onclick="gwGMarkerMap.setMarker( '5090', this.checked );" id="showmarker-5090"/>Show in map

  Or you may call the marker directly with:

  <script type="text/javascript" language="javascript">
  <!--
        gwGMarkerMap.addMarker({
               id: '5090',
               latitude: 9.26,
               longitude: 0.39,
               title: 'Welcome to this company.',
               url: '/content/view/full/5090',
               content: 'More detailed information',
               shadowImage: '/url/image.jpg'
               });
  // -->
  </script>
*/

var gwGMarkerMap =
{
    map: false,
    mapLanguage: 'no',
    mapLat: 59.358396,
    mapLng: 10.338135,

    southWestLat: 0,
    southWestLng: 0,
    northEastLat: 0,
    northEastLng: 0,

    enableScrollwheel: false,

    directionsDisplay: new google.maps.DirectionsRenderer(),

    zoomValue: 8,
    googleHrefZoom: 12,
    zoomToFitValue: 0.1,
    zoomDivider: 6,

    mapCanvas: false,
    elementHeight: 200,
    maxElementHeight: 400,

    infoWindow: new Array(),
    infoWindowList: new Array(),
    minInfoWindowWidth: 250,
    useInfoWindow: true,
    activeInfoWindow: false,
    activeInfoID: false,

    showCalcRouteText: true,

    mapPoints: new Array(),
    markers: new Array(),
    markerIconList: new Array(),
    showMarkerPrefix: 'showmarker-',

    inputMarkerIDListName: 'gwGMarkerMapIDList[]',
    inputMarkerLatPrefix: 'gwGMarkerMapLat-',
    inputMarkerLngPrefix: 'gwGMarkerMapLng-',
    inputMarkerNamePrefix: 'gwGMarkerMapName-',
    inputMarkerURLPrefix: 'gwGMarkerMapURL-',
    inputMarkerContentPrefix: 'gwGMarkerMapContent-',
    inputMarkerShadowImagePrefix: 'gwGMarkerMapShadowImage-',
    inputMarkerToggleName: 'gwGMarkerMapToggle',

    inputDestination: 'gwGMarkerMapDestination',

    directionsID: 'google-directions',

    routeText: 'Drive from',
    readMore: 'Read more',
    titleTag: 'b',

    mapTypeIds: [ google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.TERRAIN, google.maps.MapTypeId.SATELLITE, google.maps.MapTypeId.HYBRID ],

    /*!
      Public functions
    */
    initialize: function( id )
    {
        gwGMarkerMap.clearAll();
        gwGMarkerMap.createMap( id );
    },

    setMarker: function( id, value )
    {
        var key = 'marker' + id;
        marker = gwGMarkerMap.markers[key];
        marker.setVisible( value );
        if ( value == false )
        {
            gwGMarkerMap.closeInfoWindow( id );
        }
        gwGMarkerMap.updateShowMarker( value );
        gwGMarkerMap.zoomToFit();
    },

    toggleMarkers: function( value )
    {
        var markerElements = document.getElementsByName( gwGMarkerMap.inputMarkerIDListName );

        for ( var index = 0; index < markerElements.length; index++ )
        {
            if ( markerElements[index] )
            {
                var id = gwGMarkerMap.showMarkerPrefix + markerElements[index].value;
                var markerCheckbox = document.getElementById( id );
                markerCheckbox.checked = value;
                gwGMarkerMap.setMarker( markerElements[index].value, value );
            }
        }
    },

    addAllMarkers: function()
    {
        var markerElements = document.getElementsByName( gwGMarkerMap.inputMarkerIDListName );

        for ( var index = 0; index < markerElements.length; index++ )
        {
            if ( markerElements[index] )
            {
                value = markerElements[index].value;
                gwGMarkerMap.addMarkerDataFromID( value );
            }
        }
    },

    resetMarkerShadowIconList: function()
    {
       for ( var index = 0; index < gwGMarkerMap.markerIconList.length; index++ )
       {
           if ( gwGMarkerMap.markerIconList[index] )
           {
                gwGMarkerMap.markerIconList[index].setShadow( '' );
           }
       }
    },

    calcShadowImageHeight: function( marker )
    {
        var height = gwGMarkerMap.northEastLat - gwGMarkerMap.southWestLat;

        var markerHeight = marker.position.lat() - gwGMarkerMap.southWestLat;

        var re = new RegExp( 'px', 'g' );
        var mapHeight = parseInt( gwGMarkerMap.mapCanvas.style.height.replace( re, '' ) );
        var markerHeightpx = mapHeight / height * markerHeight;

        var markerHeightValue = 60;
        if ( markerHeightpx > 210 )
        {
            var val = markerHeightpx - 210;
            markerHeightValue -= val;
        }
        else if ( markerHeightpx < 80 )
        {
            var val = 80 - markerHeightpx ;
            markerHeightValue += val;
        }
        return markerHeightValue;
    },

    calcShadowImageWidth: function( marker )
    {
        var width = gwGMarkerMap.northEastLng - gwGMarkerMap.southWestLng;

        var markerWidth = gwGMarkerMap.northEastLng - marker.position.lng();

        var mapWidth = gwGMarkerMap.getElementWidth();
        var markerWidthpx = mapWidth / width * markerWidth;

        var markerWidthValue = -30;
        if ( markerWidthpx < 180 )
        {
            markerWidthValue = 180;
        }
        return markerWidthValue;
    },

    addMarker: function( userData )
    {
        var id = userData.id;
        var longitude = parseFloat( userData.longitude );
        var latitude = parseFloat( userData.latitude );
        var title = userData.title;
        var iconImage = userData.iconImage;
        var shadowImage = userData.shadowImage;
        var showDirections=userData.showDirections;
        

        var gwLatlng = new google.maps.LatLng( latitude, longitude );
        

        var marker = new google.maps.Marker({
              position: gwLatlng,
              map: gwGMarkerMap.map,
              title: title,
              showDirections: showDirections
            });
                            
        if ( iconImage && iconImage != '' )
        {
            marker.setIcon( iconImage );
        }

        if ( shadowImage && shadowImage != '' )
        {
            marker.setShadow( shadowImage );
            
            /*google.maps.event.addListener(marker, "mouseover", function() {
                // clear all other icons.
                gwGMarkerMap.resetMarkerShadowIconList();

                var markerHeightValue = gwGMarkerMap.calcShadowImageHeight( marker );
                var markerWidthValue = gwGMarkerMap.calcShadowImageWidth( marker );

                var markerIcon = new google.maps.MarkerImage( shadowImage );
                markerIcon.anchor = new google.maps.Point( markerWidthValue, markerHeightValue );
                marker.setShadow( markerIcon );
                gwGMarkerMap.markerIconList.push( marker );
            });

            google.maps.event.addListener(marker, "mouseout", function() {
                marker.setShadow( '' );
            });*/
        }

        gwGMarkerMap.mapPoints.push( {position: gwLatlng} );
        gwGMarkerMap.markers['marker' + id] = marker;
        if ( gwGMarkerMap.useInfoWindow == true )
        {
            gwGMarkerMap.addInfoWindow( marker, userData );
        }
    },

    zoomToFit: function()
    {
        if ( gwGMarkerMap.mapPoints.length > 0 )
        {
            var bounds = new google.maps.LatLngBounds();
            for (var i = 0, LtLgLen = gwGMarkerMap.mapPoints.length; i < LtLgLen; i++) {
                // And increase the bounds to take this point
                bounds.extend( gwGMarkerMap.mapPoints[i].position );
            }

            bounds = gwGMarkerMap.setMinSize( bounds, gwGMarkerMap.zoomToFitValue );
            gwGMarkerMap.map.fitBounds( bounds );
        }
    },

    updateGoogleHref: function( latLng )
    {
        var bounds = new google.maps.LatLngBounds();
        bounds.extend( latLng );
        var url = '';
        var formattedAddress = '';
        if ( bounds != undefined )
        {
            var url = 'http://maps.google.com/maps?f=d' +
                '&amp;source=s_d' +
                '&amp;daddr=' +
                '&amp;geocode=' +
                '&amp;mra=dme' +
                '&amp;mrcr=0' +
                '&amp;mrsp=0' +
                '&amp;sz=' + gwGMarkerMap.googleHrefZoom +
                '&amp;hl=' + gwGMarkerMap.mapLanguage +
                '&amp;sll=' + bounds.getSouthWest().toUrlValue() +
                '&amp;ll=' + latLng.lat() + ',' + latLng.lng() +
                '&amp;z=' + gwGMarkerMap.googleHrefZoom;
        }
        return url;
    },

    setCenter: function()
    {
        if ( gwGMarkerMap.mapPoints.length == 1 )
        {
            gwGMarkerMap.map.setCenter( gwGMarkerMap.mapPoints[0].position );
        }
    },

    clearAll: function()
    {
        gwGMarkerMap.map = false;
        gwGMarkerMap.infoWindow = new Array();
        gwGMarkerMap.infoWindowList = new Array();
        gwGMarkerMap.mapPoints = new Array();
        gwGMarkerMap.markers = new Array();
    },

    setHeight: function( id, value )
    {
        var element = document.getElementById( id );
        gwGMarkerMap.mapCanvas = element;
        gwGMarkerMap.mapCanvas.style.height = value + 'px';
    },

    addStatkartLayer: function( type, name )
    {
        gwGMarkerMap.map.mapTypes.set( 'statkart-' + type, new google.maps.ImageMapType(
        {
            name: name? name: type,
            tileSize: new google.maps.Size( 256, 256 ),
            maxZoom: 19,
            getTileUrl: function( coord, zoom )
            {
                return 'http://opencache.statkart.no/gatekeeper/gk/gk.open_gmaps?layers=' + type + "&zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y;
            }
        } ) );
        gwGMarkerMap.mapTypeIds.push( 'statkart-' + type );
        gwGMarkerMap.map.setOptions( { mapTypeControlOptions: { mapTypeIds: gwGMarkerMap.mapTypeIds } } );
        gwGMarkerMap.map.setMapTypeId( 'statkart-' + type );
    },

    addKML: function( kmlURL )
    {
        var ctaLayer = new google.maps.KmlLayer( kmlURL );
        ctaLayer.setMap( gwGMarkerMap.map );
    },

    /*!
      Private functions
    */
    createMap: function( id )
    {
        var latlng = new google.maps.LatLng( gwGMarkerMap.mapLat, gwGMarkerMap.mapLng );

        var myOptions =
        {
            zoom: gwGMarkerMap.zoomValue,
            center: latlng,
            scrollwheel: gwGMarkerMap.enableScrollwheel,
            scaleControl: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            mapTypeControlOptions: { mapTypeIds: gwGMarkerMap.mapTypeIds }
        };

        gwGMarkerMap.mapCanvas = document.getElementById( id );
        gwGMarkerMap.map = new google.maps.Map( gwGMarkerMap.mapCanvas, myOptions );

        google.maps.event.addListener(gwGMarkerMap.map, "idle", function() {
            var bounds = this.getBounds();

            gwGMarkerMap.southWestLat = bounds.getSouthWest().lat();
            gwGMarkerMap.southWestLng = bounds.getSouthWest().lng();
            gwGMarkerMap.northEastLat = bounds.getNorthEast().lat();
            gwGMarkerMap.northEastLng = bounds.getNorthEast().lng();
        });
    },

    calcRouteFromInput: function()
    {
        try
        {
            if ( gwGMarkerMap.activeInfoWindow != false )
            {
                var destination = document.getElementById( gwGMarkerMap.inputDestination );
                if ( destination.value != '' )
                {
                    var from = gwGMarkerMap.activeInfoWindow.getPosition();
                    gwGMarkerMap.calcRoute( from, destination.value );
                    var infoID = gwGMarkerMap.activeInfoID;
                    if ( infoID != false && gwGMarkerMap.infoWindow[infoID] != undefined && gwGMarkerMap.infoWindow[infoID] != false )
                    {
                        var infoWindow = gwGMarkerMap.infoWindow[infoID];
                        if ( infoWindow )
                        {
                            infoWindow.close();
                        }
                        gwGMarkerMap.resetMarkerShadowIconList();
                    }
                }
            }
        }
        catch ( e )
        {
        }
        return false;
    },

    calcRoute: function( from, to )
    {
        var directionsService = new google.maps.DirectionsService();
        var selectedMode = 'DRIVING';
        var unitSystem = 'METRIC';

        var request = {
            origin: to,
            destination: from,
            travelMode: google.maps.DirectionsTravelMode[selectedMode],
            unitSystem: google.maps.DirectionsUnitSystem[unitSystem],
            provideRouteAlternatives: true,
            optimizeWaypoints: true
        };

        var result = false;
        var status = false;
        directionsService.route( request, function(response, status){
            if (status == google.maps.DirectionsStatus.OK) {
                gwGMarkerMap.directionsDisplay.setMap( gwGMarkerMap.map );
                gwGMarkerMap.directionsDisplay.setDirections( response );

                var directionPanel = document.getElementById( gwGMarkerMap.directionsID );
                gwGMarkerMap.directionsDisplay.setPanel( directionPanel );
            }
            else
            {
                alert( 'Fant ikke "' + to + '"' );
            }
        });

        return false;
    },

    setMinSize: function( bounds, value )
    {
        var northEast = bounds.getNorthEast();
        var southWest = bounds.getSouthWest();

        var latDiff = northEast.lat() - southWest.lat();
        var lngDiff = northEast.lng() - southWest.lng();

        var level = value / gwGMarkerMap.zoomDivider;

        if ( latDiff < value ||
             lngDiff < value )
        {
            var newLat = northEast.lat() + level;
            var newLng = northEast.lng() + level;

            var gwLatlng = new google.maps.LatLng( newLat, newLng );
    		bounds.extend( gwLatlng );

            newLat = southWest.lat() - level;
            newLng = southWest.lng() - level;

            gwLatlng = new google.maps.LatLng( newLat, newLng );
    		bounds.extend( gwLatlng );
        }
        return bounds;
    },

    addMarkerDataFromID: function( id )
    {
        var latitude = document.getElementById( gwGMarkerMap.inputMarkerLatPrefix + id );
        var longitude = document.getElementById( gwGMarkerMap.inputMarkerLngPrefix + id );
        var title = document.getElementById( gwGMarkerMap.inputMarkerNamePrefix + id );
        var url = document.getElementById( gwGMarkerMap.inputMarkerURLPrefix + id );
        var content = document.getElementById( gwGMarkerMap.inputMarkerContentPrefix + id );
        var shadowImage = document.getElementById( gwGMarkerMap.inputMarkerShadowImagePrefix + id );
        var shadowImage = document.getElementById( gwGMarkerMap.inputMarkerShadowImagePrefix + id );

        var data = { id: id,
                     latitude: 0,
                     longitude: 0,
                     title: '',
                     url: '',
                     content: '',
                     shadowImage: '',
                     showDirections:false};

        if ( latitude != undefined )
           data.latitude = latitude.value;

        if ( longitude != undefined )
           data.longitude = longitude.value;

        if ( title != undefined )
           data.title = title.value;

        if ( url != undefined )
           data.url = url.value;

        if ( content != undefined )
           data.content = content.value;

        if ( shadowImage != undefined )
           data.shadowImage = shadowImage.value;
        
        if (showDirections != undefined)
            data.showDirections = showDirections.value

        gwGMarkerMap.addMarker( data );
    },

    updateShowMarker: function( value )
    {
        var showMarkerCheckbox = document.getElementById( gwGMarkerMap.inputMarkerToggleName );
        if ( showMarkerCheckbox != undefined )
        {
            if ( value == false )
            {
                showMarkerCheckbox.checked = false;
            }
            else if ( value == true )
            {
                var markerElements = document.getElementsByName( gwGMarkerMap.inputMarkerIDListName );
                var markerTest = true;
                for ( var index = 0; index < markerElements.length; index++ )
                {
                    if ( markerElements[index] )
                    {
                        var id = gwGMarkerMap.showMarkerPrefix + markerElements[index].value;
                        var markerCheckbox = document.getElementById( id );
                        if ( markerCheckbox.checked != true )
                        {
                            showMarkerCheckbox.checked = false;
                            markerTest = false;
                            break;
                        }
                    }
                }
                if ( markerTest == true )
                {
                    showMarkerCheckbox.checked = true;
                }
            }
        }
    },

    fetchInfoWindow: function( id )
    {
        var infoWindow = false;
        var key = 'w' + id;
        if ( gwGMarkerMap.infoWindow[key] )
        {
            var infoWindow = gwGMarkerMap.infoWindow[key];
        }
        return infoWindow;
    },

    closeInfoWindow: function( id )
    {
        var value = false;
        var infoWindow = gwGMarkerMap.fetchInfoWindow( id );
        if ( infoWindow )
        {
            infoWindow.close();
            value = true;
        }
        return value;
    },

    calcRouteInfoText: function()
    {
        var value = '';
        if ( gwGMarkerMap.showCalcRouteText == true )
        {
            value = '<form action="" method="post" style="margin: 0; padding: 0; font-size: 9px;" onsubmit="gwGMarkerMap.calcRouteFromInput(); return false;">' +
                    '<p>' + gwGMarkerMap.routeText + ': ' +
                    '<input type="text" name="gwGMarkerMapDestination" id="gwGMarkerMapDestination" value=""' +
                    'onblur="gwGMarkerMap.calcRouteFromInput(); return false;" onclick="return false;" onkeypress="return gwGMarkerMap.handleEnterButton( event );" /></p></form>';
        }
        return value;
    },

    handleEnterButton: function( e )
    {
        var keyCode = (window.Event) ? e.which : e.keyCode;
        if ( keyCode == 13 )
        {
            gwGMarkerMap.calcRouteFromInput();
            return false;
        }

        return true;
    },

    createGoogleLink: function( url )
    {
        var value = '<a href="' + url + '" target="_blank">Google</a>';
        return value;
    },

    createReadmoreLink: function( url )
    {
        var value = '<br />' + '<a href="' + url + '">' + gwGMarkerMap.readMore + '</a>';
        return value;
    },
    createDirectionsLink: function()
    {
        var value = '<p>' + gwGMarkerMap.calcRouteInfoText() + '</p>' ;
        return value;
    },    

    createTitle: function( title )
    {
        var value = '<' + gwGMarkerMap.titleTag + '>' + title + '</' + gwGMarkerMap.titleTag + '>';
        return value;
    },

    createBody: function( content )
    {
        var value =  '<br />' + content + '<br />';
        return value;
    },

    addInfoWindow: function ( marker, userData )
    {
        var width = gwGMarkerMap.getElementWidth();
        if ( width > gwGMarkerMap.minInfoWindowWidth )
        {
            var id = userData.id;
            var longitude = parseFloat( userData.longitude );
            var latitude = parseFloat( userData.latitude );
            var title = userData.title;
            var url = userData.url;
            var content = userData.content;
            var showDirections = userData.showDirections;
           

            value = gwGMarkerMap.createTitle( title );

            if ( content != undefined && content != '' )
            {
                value += gwGMarkerMap.createBody( content );
            }

            if ( url != undefined && url != '' )
            {
                value += gwGMarkerMap.createReadmoreLink( url );
            }
            
            if ( showDirections )
            {
                value += gwGMarkerMap.createDirectionsLink();
            }

            var googleUrl = gwGMarkerMap.updateGoogleHref( marker.getPosition() );
            var params = { 'value': value,
                           'marker': marker,
                           'user_data': userData,
                           'google_url': googleUrl };

            if ( googleUrl != '' )
            {
                gwGMarkerMap.createSAddrInfoWindow( params );
            }
            else
            {
                gwGMarkerMap.createInfoWindow( params );
            }
        }
    },

    createSAddrInfoWindow: function( params )
    {
        var latLng = params.marker.getPosition();
        var googleUrl = params.google_url;
        var value = params.value;

        googleUrl += '&amp;saddr=' + latLng.lat() + ',' + latLng.lng();

        var googleLink = gwGMarkerMap.createGoogleLink( googleUrl );
        //value += '<div>' + googleLink + '</div>';
        params.value = value;

        gwGMarkerMap.createInfoWindow( params );
    },

    createGMapInfoWindow: function( params )
    {
        var latLng = params.marker.getPosition();
        var googleUrl = params.google_url;
        var value = params.value;

        var geocoder = new google.maps.Geocoder();
        if ( geocoder )
        {
            geocoder.geocode({'latLng': latLng}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    formattedAddress = results[1].formatted_address;
                    googleUrl += '&amp;q=' + formattedAddress + '@' + latLng.lat() + ',' + latLng.lng();
                }
                else
                {
                    googleUrl += '&amp;saddr=' + latLng.lat() + ',' + latLng.lng();
                }

                //var googleLink = gwGMarkerMap.createGoogleLink( googleUrl );
                value += ' ' + googleLink;
                params.value = value;
                gwGMarkerMap.createInfoWindow( params );
            } );
        }
        else
        {
            gwGMarkerMap.createInfoWindow( params );
        }
    },

    createInfoWindow: function( params )
    {
        var value = params.value;
        var id = params.user_data.id;

        var marker = params.marker;
        value = '<div class="infowindow-content" style="font-size: 14px; margin-right: 15px; white-space: nowrap; overflow-x:hidden;  overflow-y:hidden;">' + value + '</div>';

        var infoWindowKey = 'w' + id;
        gwGMarkerMap.infoWindow[infoWindowKey] = new google.maps.InfoWindow({
               content: value
        });


        google.maps.event.addListener( marker, 'click', function() {
            gwGMarkerMap.activeInfoWindow = false;
            gwGMarkerMap.activeInfoID = false;

            for ( var i=0; i<gwGMarkerMap.infoWindowList.length; i++ )
            {
                gwGMarkerMap.closeInfoWindow( gwGMarkerMap.infoWindowList[i]);
            }

            gwGMarkerMap.infoWindow[infoWindowKey].open( gwGMarkerMap.map, marker );
            gwGMarkerMap.activeInfoWindow = marker;
            gwGMarkerMap.activeInfoID = infoWindowKey;
        });

        gwGMarkerMap.infoWindowList.push( id );
    },

    updateCanvasHeight: function()
    {
        var mapElement = gwGMarkerMap.mapCanvas;
        var elementWidth = gwGMarkerMap.getElementWidth();

        mapElement.style.width = elementWidth + 'px';
        var height = ( elementWidth / 4 * 3 );
        if ( height > gwGMarkerMap.maxElementHeight )
        {
             height = gwGMarkerMap.maxElementHeight;
        }
        mapElement.style.height = height + 'px';
    },

    getElementWidth: function()
    {
        var element = gwGMarkerMap.mapCanvas;
        if ( element.currentStyle )
        {
            var width = element.offsetWidth.toString();
        }
        else
        {
            var width = document.defaultView.getComputedStyle( element, '' ).getPropertyValue('width').toString();
        }

        return parseInt( width.replace(/\px/, "") );
    }
}

