var dovoGMap = {

    map: undefined,
    geocoder: undefined,

    myposition: undefined,
    myaddress: undefined,
    mymarker: undefined,
    bounds: undefined,

    marker_selected: undefined, // holds currently selected marker

    initialize: function() {
        var myOptions = {
            zoom: 8,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        dovoGMap.map = new google.maps.Map( document.getElementById("map"), myOptions );
        dovoGMap.geocoder = new google.maps.Geocoder();
    },

    geolocateMyPosition: function(opt) {
        if( navigator.geolocation ) {
            navigator.geolocation.getCurrentPosition( function(position) {
                dovoGMap.myposition = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
                dovoGMap.geocoder.geocode( {'latLng': dovoGMap.myposition}, function(results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        if (results[0]) {
                            dovoGMap.myaddress = results[0].formatted_address;
                            dovoGMap.setMyMarker( opt.radius );
                            if (opt.callback) opt.callback( dovoGMap.myposition.lat(), dovoGMap.myposition.lng(), dovoGMap.myaddress );
                            return;
                        }
                    }
                });
            }, function(error) {
                var message = dovoGMap._geoError( error );
                if ( opt.callbackError ) { opt.callbackError( message ); }
            }, {maximumAge: 600000} );
            return true;
        }
        else {
            return false;
        }
    },

    geocodeMyAddress: function(opt) {
        if ( opt.address != '' ) {
            dovoGMap.geocoder.geocode( {'address': opt.address}, function(results, status) {
                if ( status == google.maps.GeocoderStatus.OK ) {
                    dovoGMap.myposition = results[0].geometry.location;
                    dovoGMap.myaddress = results[0].formatted_address;
                    dovoGMap.setMyMarker( opt.radius );
                    if (opt.callback) opt.callback( dovoGMap.myposition.lat(), dovoGMap.myposition.lng(), dovoGMap.myaddress );
                }
            });
        }
    },

    resetMyMarker: function() {
        if ( dovoGMap.mymarker ) {
            dovoGMap.mymarker.setMap(null);
            dovoGMap.mymarker.circle.setMap(null);
        }
    },

    setMyMarker: function( radius ) {
        dovoGMap.resetMyMarker();
        dovoGMap.map.setCenter( dovoGMap.myposition );

        // highlight area
        var circleOptions = {
            strokeColor: "#ff5a25",
            strokeOpacity: 0.5,
            fillColor: "#ff5a25",
            fillOpacity: 0.2,
            center: dovoGMap.myposition,
            radius: radius,
            map: dovoGMap.map,
            editable: false
        };
        var circle = new google.maps.Circle(circleOptions);
        var icon = new google.maps.MarkerImage( "/images/pin-myself.png?1328232488",
                                                new google.maps.Size(32, 32),   // size
                                                null,                           // origin
                                                new google.maps.Point(16, 16)); // anchor
        dovoGMap.mymarker = new google.maps.Marker({
            map: dovoGMap.map,
            position: dovoGMap.myposition,
            title: dovoGMap.myaddress,
            circle: circle,
            icon: icon
        });
    },

    addEventToMap: function(options) {
        options.map = dovoGMap.map;
        var marker = dovoGMap.marker( options );
        return marker;
    },

    setZoom: function() {
        dovoGMap.bounds = new google.maps.LatLngBounds();
        $.each( dovoEvents.events, function(i, event) {
            dovoGMap.bounds.extend( event.marker.position() );
        });
        dovoGMap.map.fitBounds( dovoGMap.bounds );
    },

    _geoError: function(error) {
        switch (error.code) {
        case error.PERMISSION_DENIED:
	          return "Sorry, but I'm unable to locate your position. Authorize the application or manually set your position.";
        case error.POSITION_UNAVAILABLE:
        case error.TIMEOUT:
	          return "Sorry, but I'm unable to locate your position. Manually set your position.";
        };
    }

};

// Marker object
// functional approach - thanks D. Crockford
dovoGMap.marker = function(options) {
    var that = {};
    var map  = options.map;
    var lat  = options.lat;
    var lng  = options.lng;
    var name = options.name;
    var event_id = "#" + options.id;
    var selected = false;

    var info = new InfoBubble({
        content: name,
        shadowStyle: 1,
        backgroundColor: '#393939',
        padding: 0,
        borderRadius: 4,
        arrowSize: 10,
        borderWidth: 1,
        borderColor: '#393939',
        hideCloseButton: true,
        backgroundClassName: 'infobubble',
        minHeight: '40',
        arrowStyle: 0
    });
    var icon = new google.maps.MarkerImage( "/images/pin.png?1328232488",
                                            new google.maps.Size(15, 29),
                                            new google.maps.Point(0, 0),
                                            new google.maps.Point(8, 29));
    var shadow = new google.maps.MarkerImage( "/images/pin_shadow.png?1328232488",
                                              new google.maps.Size(25, 29),
                                              new google.maps.Point(0, 0),
                                              new google.maps.Point(2, 29) );
    var marker = new google.maps.Marker({
        map: map,
        position: new google.maps.LatLng( lat, lng ),
        icon: icon,
        shadow: shadow,
        title: name,
        animation: google.maps.Animation.DROP
    });
    google.maps.event.addListener( marker, 'click', function() {
        $('html, body').animate( {scrollTop: $(event_id).position().top -5 }, 'fast' );
        $(event_id).click();
    });

    // Public methods
    that.closeInfo = function() {
        info.close();
        selected = false;
        dovoGMap.marker_selected = null;
    };

    that.openInfo = function() {
        if ( dovoGMap.marker_selected && that !== dovoGMap.marker_selected ) {
            dovoGMap.marker_selected.closeInfo();
        }
        info.open( map, marker );
        map.panTo( marker.position );
        map.setZoom( 14 );
        dovoGMap.marker_selected = that;
        selected = true;
    };

    that.toggleInfo = function() {
        if ( selected ) {
            that.closeInfo();
        }
        else {
            that.openInfo();
        }
    };

    that.position = function() {
        return marker.position;
    };

    that.remove = function() {
        info.close();
        marker.setMap(null);
    };

    return that;
};

