/*!
  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,

    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',

    /*!
      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( '' );
           }
       }
    },

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

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

        var marker = new google.maps.Marker({
              position: gwLatlng,
              map: gwGMarkerMap.map,
              title: title
                            });

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

                var markerIcon = new google.maps.MarkerImage( shadowImage );
                markerIcon.anchor = new google.maps.Point( -30, 60 );
                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 )
        {
// http://maps.google.com/maps?f=d&source=s_d&saddr=59.416898,10.485463&daddr=&geocode=&hl=no
// &mra=dme&mrcr=0&mrsp=0&sz=15&sll=59.420282,10.486794&sspn=0.01596,0.061884&ie=UTF8&z=15
            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';
    },

    /*!
      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
        };

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

    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 data = { id: id,
                     latitude: 0,
                     longitude: 0,
                     title: '',
                     url: '',
                     content: '',
                     shadowImage: '' };

        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;

        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 />' + gwGMarkerMap.calcRouteInfoText() + '<a href="' + url + '">' + gwGMarkerMap.readMore + '</a>';
        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;

            value = gwGMarkerMap.createTitle( title );

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

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

            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 += ' ' + googleLink;
        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="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/, "") );
    }
}

