var glatlng;
var gmarker;
var manager;
var tooltip;
var zoom    = 8;
var gmap    = null;

/* Collection of POIs */
var points = [];

/* Initialize */
function initialize (container, options) {

    var container = container ? container : 'listings-map';
    var defaults  = {
        'tooltip' : true,
        'bounds_center' : true,
        'bounds_zoom' : true
    };
    var options   = options   ? options : defaults;

    if (gmap != null) return;

    /* Create Map */
    gmap = new GMap2(document.getElementById(container));

    /* Center Map */
    gmap.setCenter(glatlng, zoom);

    /* Add 3D Map Control */
    gmap.addControl(new GLargeMapControl3D());

    /* Add Map Type Controls */
    gmap.addMapType(G_PHYSICAL_MAP);
    var hControl = new GHierarchicalMapTypeControl();
    hControl.addRelationship(G_SATELLITE_MAP, G_HYBRID_MAP, "Labels", true);
    gmap.addControl(hControl);

    /* Enable Scroll Wheel Zoom */
    gmap.enableScrollWheelZoom();

    /* POI Manager */
    manager = new MapMarkerManager (gmap, points, {
        'bounds_center' : (typeof(options.bounds_center) != 'undefined') ? options.bounds_center : defaults.bounds_center,
        'bounds_zoom'   : (typeof(options.bounds_zoom)   != 'undefined') ? options.bounds_zoom   : defaults.bounds_zoom
    });
    manager.plot();

    /* Map Tooltip */
    options.tooltip = (typeof(options.bounds_center) != 'undefined') ? options.tooltip : defaults.tooltip;
    if (options.tooltip) {
        tooltip = new MapTooltip('map-label');
    }

}

function MapMarker (title, latitude, longitude, html, options) {

    /* Marker Instance */
    var $marker = this;

    /* Marker Options */
    $marker.options = options ? options : {};

    /* Marker Parameters */
    $marker.title      = title;
    $marker.latitude   = latitude;
    $marker.longitude  = longitude;
    $marker.html       = html;
    $marker.icon       = $marker.options.icon ? $marker.options.icon : '/idx/img/map/ico-map-listing.png';
    $marker.icon            = new GIcon(G_DEFAULT_ICON, $marker.icon);
    $marker.icon.shadow     = "/idx/img/map/ico-map-shadow.png";
    $marker.icon.iconSize   = new GSize(14, 17);
    $marker.icon.shadowSize = new GSize(17, 17);
    $marker.icon.iconAnchor = new GPoint(0, 0);
    $marker.icon.infoWindowAnchor = new GPoint(0, 0);
    $marker.icon.infoShadowAnchor = new GPoint(0, 0);

    /* Marker Point */
    $marker.point = new GLatLng ($marker.latitude, $marker.longitude);

    /* Google Marker */
    $marker.marker = new GMarker($marker.point, {
        icon: $marker.icon,
        title: $marker.title
    });

    /* Select Marker */
    $marker.select = function () {
        /* Trigger Marker Click */
        GEvent.trigger($marker.marker, 'click');
    };

}

function MapMarkerManager (map, points, options) {

    /* Manager Instance */
    var $manager = this;

    /* Manager Parameters */
    $manager.map     = map;
    $manager.options = options || {};
    $manager.points  = [];

    /* Manager Bounds */
    $manager.bounds = new GLatLngBounds();

    /* Add New MapMarker */
    $manager.addMarker = function (marker) {

        /* Marker Index */
        var index = $manager.points.length;

        /* Add to Collection */
        $manager.points[index] = marker;

        /* Extend Bounds */
        $manager.bounds.extend(marker.point);

    };

    /* Add Points */
    $.each(points, function (index) {
        $manager.addMarker(this);
    });

    /* Select Existing Marker */
    $manager.selectMarker = function (title) {

        /* Find Marker */
        var marker = $manager.getMarker(title);
        if (marker) {

            /* Select Marker */
            marker.select();

        }

    };

    /* Get Marker by Title */
    $manager.getMarker = function (title) {

        var marker = null;

        /* Loop through Markers */
        $.each($manager.points, function (index) {

            /* Match Against Title */
            if (title == this.title) {
                marker = $manager.points[index];
                return;
            }

        });

        /* Return Marker */
        return marker;

    };

    /* Plot Manager Points */
    $manager.plot = function (points) {

        /* Points to Plot */
        if (typeof(points) != 'undefined') {
            $.each(points, function () {
                $manager.addMarker(this);
            });
        }

        /* Loop through Marker Collection */
        $.each($manager.points, function () {

            /* Set Scope */
            var marker = this.marker;
            var html   = this.html;

            /* Add to Map */
            gmap.addOverlay(marker);

            /* Attach Onclick Event */
            GEvent.addListener(marker, 'click', function() {

                /* Open Tooltip */
                if (tooltip) {
                    /* Show Tooltip */
					if ($('#map-label:hidden')) {
						tooltip.show(marker, html, true);
					}
                }

            });

            /* Attach Mouse Over Event */
            GEvent.addListener(marker, 'mouseover', function() {
                /* Show Tooltip */
				if ($('body').hasClass('mapHasSticky')) {
                	// do nothing
                } else {
                	if (tooltip) tooltip.show(marker, html);
                }
            });

            /* Attach Mouse Out Event */
            GEvent.addListener(marker, 'mouseout', function() {
                /* Hide Tooltip */
                if (tooltip) tooltip.hide();
            });

        });

        /* Fit All Markers within Map */
        if (manager.bounds.getCenter().lat() != 0) {
            if ($manager.options.bounds_center) {
                gmap.setCenter(manager.bounds.getCenter());
            }
            if ($manager.options.bounds_zoom) {
                gmap.setZoom(gmap.getBoundsZoomLevel(manager.bounds));
            }
        }

    };

    /* Reset Marker Manager */
    $manager.reset = function () {

        /* Hide Tooltip */
		if (tooltip) tooltip.hide(true);

        /* Loop through Marker Collection */
        $.each($manager.points, function () {

            /* Remove Listeners */
            GEvent.clearInstanceListeners(this.marker);

            /* Remove Overlay */
            gmap.removeOverlay(this.marker);

        });

        /* Reset Points */
        $manager.points = [];

        /* Reset Bounds */
        $manager.bounds = new GLatLngBounds();

    };

}


function MapTooltip (elem, options) {

    /* Tooltip Instance */
    var $tooltip = this;

    /* Over */
    $tooltip.over = false;

    /* Sticky */
    $tooltip.sticky = false;

    /* Tooltip Options */
    $tooltip.options = options ? options : {};

    /* Tooltip Timout Delay */
    $tooltip.delay = $tooltip.options.delay ? $tooltip.options.delay : 500;

    /* Create Container */
    $('body').append('<div id="' + elem + '" style="position: absolute; z-index: 300; display: none;"></div>');

    /* Tooltip Container */
    var $contain = $('#' + elem);

    /* Container Mouseover */
    $contain.bind('mouseover', function () {
        $tooltip.over = true;
    });

    /* Container Mouseout */
    $contain.bind('mouseout', function () {
        $tooltip.hide();
    });

    /* Show MapTooltip */
    $tooltip.show = function (marker, html, sticky) {

   		$tooltip.over   = true;
		$tooltip.sticky = (typeof(sticky) != 'undefined') ? sticky : false;
		var offset = gmap.fromLatLngToContainerPixel(marker.getLatLng());
		$contain.show().css({
			position: 'absolute',
			top:  $('#' + gmap.getContainer().id).offset().top  + offset.y + 10 + 'px',
			left: $('#' + gmap.getContainer().id).offset().left + offset.x + 10 + 'px'
		}).html(html);
		if(sticky) {
			$close = ('<a href="javascript:void(0);" class="action-close">hide</a>');
			$('body').addClass('mapHasSticky');
			$('.title',$contain).append($close);
			$('.action-close',$contain).click(function(){
				$contain.hide();
				$('body').removeClass('mapHasSticky');
			});
		} else {
			$contain.removeClass('sticky');
		}
    };

    /* Hide MapTooltip */
    $tooltip.hide = function (force) {
        if (force == true) {
            $contain.hide();
            $('body').removeClass('mapHasSticky');
        }
        if ($tooltip.sticky) return;
        $tooltip.over = false;
        clearTimeout($tooltip.timeout);
        $tooltip.timeout = setTimeout(function () {
            if ($tooltip.over == false) {
                $contain.hide();
                $('body').removeClass('mapHasSticky');
            }
        }, $tooltip.delay);
    };

}
