var glatlng;
var gmarker;
var manager;
var tooltip;
var zoom    = 12;
var gmap    = null;
var loader  = null;

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

/* Map State Cookie */
var cookie_name = 'rew-map';

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

    var container = container ? container : 'listings-map';

    var defaults  = {
        'map_cache' : true,
        'map_type' : G_NORMAL_MAP,
        'loader'   : false,
        'tooltip'  : true,
        'control_types' : true,
        'bounds_center' : true,
        'bounds_zoom'   : true
    };

    var options   = options   ? options : defaults;

    if (gmap != null) return;

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

    /* Set Map Type */
    options.map_type = (typeof(options.map_type) != 'undefined') ? options.map_type : defaults.map_type;
    if (options.map_type) {
        gmap.setMapType(options.map_type);
    }

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

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

    /* Add Map Type Controls */
    options.control_types = (typeof(options.control_types) != 'undefined') ? options.control_types : defaults.control_types;
    if (options.control_types) {
        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 Loader Overlay */
    options.loader = (typeof(options.loader) != 'undefined') ? options.loader : defaults.loader;
    if (options.loader) {
        loader = new MapLoader ();
    }

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

    /* Attach Save State on Move End */
    GEvent.addListener(gmap, 'moveend', function () {
        mapSave();
    });

    /* Restore Saved Map State */
    if (options.map_cache) mapRestore();

}

/**
 * Create Marker
 */
function createMarker (point, html, icon) {

    /* Create Marker */
    var marker = new GMarker(point, {icon: icon});

    /* 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 (tooltip) {
    	    if ($('body').hasClass('mapHasSticky')) return;
           tooltip.show(marker, html);
        }
    });

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

    /* Return GMarker */
    return marker;

}

/**
 * Format Number
 */
function formatNumber (number) {
    if (typeof(number) == 'undefined' || typeof(number) == 'object') return 0;
	x = number.toString();
	iLen = x.length;
	pos = x.indexOf(".");
	if (pos > -1){
		iLen = pos;
	}
	var temp = "";
	temp = x.substring(0, iLen);
	for (var i = 0; i < Math.floor((temp.length-(1+i))/3); i++){
		temp = temp.substring(0,temp.length-(4*i+3))+','+temp.substring(temp.length-(4*i+3));
	}
	return temp;
}

/* Map Marker */
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 : '/img/map/ico-home.png';
    $marker.icon            = new GIcon(G_DEFAULT_ICON, $marker.icon);
    $marker.icon.shadow     = "";
    $marker.icon.iconSize   = new GSize(19, 19);
    $marker.icon.shadowSize = new GSize(0, 0);
    $marker.icon.iconAnchor = new GPoint(0, 0);
    $marker.resultdiv       = $marker.options.resultdiv ? $marker.options.resultdiv : null;

    /* 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');
        /* Set Active Marker */
        if (typeof(manager) != 'undefined') {
            manager.activeMarker($marker);
        }
    };

    /* Highlight Marker */
    $marker.highlight = function (toggle) {
        if ($marker.resultdiv == null) return;
        var toggle = typeof(toggle) != 'undefined' ? toggle : true;
        if (toggle) {
            $($marker.resultdiv).addClass('highlight');
        } else {
            if (!$marker.isActiveMarker()) {
                $($marker.resultdiv).removeClass('highlight');
            }
        }
    };

    /* Is Active Marker */
    $marker.isActiveMarker = function () {
        if (typeof(manager) != 'undefined') {
            var active = manager.activeMarker();
            if (active != null) {
                if (active.title == $marker.title) {
                    return true;
                }
            }
        }
        return false;
    }

}

function MapMarkerManager (map, points, options) {

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

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

    /* 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);

    };

    /* Loop through Results */
    var i = 0, len = points.length;
    while (i < len) {
        $manager.addMarker(points[i]);
        i++;
    }

    /* Remove Existing Marker */
    $manager.removeMarker = function (title) {

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

            // TODO

        }

    };

    /* Set Active Marker */
    $manager.activeMarker = function (marker) {
        /* Set Active Marker */
        if (typeof(marker) != 'undefined') {
            var actifve = $manager.active;
            $manager.active = marker;
            if (actifve != null) {
                actifve.highlight(false);
            }
        }
        /* Return Active Marker */
        return $manager.active;

    };

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

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

            /* Center on Marker */
            //gmap.setCenter(marker.point);
            gmap.panTo(marker.point);

            /* 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) {

        /* Show Loader */
        if (loader) loader.show();

        /* Points to Plot */
        if (typeof(points) != 'undefined') {
            var i = 0, len = points.length;
            while (i < len) {
                $manager.addMarker(points[i]);
                i++;
            }
        }

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

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

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

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

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

                /* Highlight Marker */
                marker.highlight(true);

                /* Set Active Marker */
                $manager.activeMarker(marker);

            });

            /* Attach Mouse Over Event */
            GEvent.addListener(gmarker, 'mouseover', function() {

                /* Highlight Marker */
                marker.highlight(true);

                /* Show Tooltip */
            	if (tooltip) {
                    /* Don't Activate */
                    if ($('body').hasClass('mapHasSticky')) return;
                    if (html != '') tooltip.show(gmarker, html);
                }

            });

            /* Attach Mouse Out Event */
            GEvent.addListener(gmarker, 'mouseout', function() {

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

                /* Un-Highlight Marker */
                marker.highlight(false);

            });

            i++;

        });

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

        /* Hide Loader */
        if (loader) loader.hide();

    };

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

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

//		/* Loop through Marker Collection */
//        var i = 0, len = $manager.points.length;
//        while (i < len) {
//
//            /* Remove Listeners */
//            GEvent.clearInstanceListeners($manager.points[i].marker);
//
//            /* Remove Overlay */
//            gmap.removeOverlay($manager.points[i].marker);
//
//            /* Increment */
//            i++;
//
//        }

        /* Remove OVerlays */
        map.clearOverlays();

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

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

        /* Reset Active Marker */
        $manager.activeMarker(null);

    };

}


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 ($tooltip.sticky) {
			$close = ('<a href="javascript:void(0);" class="action-close">hide</a>');
			$('body').addClass('mapHasSticky');
			$('.title', $contain). append($close);
			$('.action-close', $contain).click(function(){
				$tooltip.hide(true);
			});
		} else {
			$contain.removeClass('sticky');
		}
    };

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

}

/* Map Loader Overlay Object */
function MapLoader (options) {

    /* Loader Instance */
    var $loader = this;

    /* Loader Options */
    $loader.options = options ? options : {};

    /* Loading Overlay */
    $loader.overlays = [];
    $loader.overlays[$loader.overlays.length] = new GPolygon([new GLatLng(-85,0),new GLatLng(85,0),new GLatLng(85,90),new GLatLng(-85,90)],null,0,0,"#000",0.4);
    $loader.overlays[$loader.overlays.length] = new GPolygon([new GLatLng(-85,90),new GLatLng(85,90),new GLatLng(85,180),new GLatLng(-85,180)],null,0,0,"#000",0.4);
    $loader.overlays[$loader.overlays.length] = new GPolygon([new GLatLng(-85,180.000001),new GLatLng(85,180.000001),new GLatLng(85,270),new GLatLng(-85,270)],null,0,0,"#000",0.4);
    $loader.overlays[$loader.overlays.length] = new GPolygon([new GLatLng(-85,270),new GLatLng(85,270),new GLatLng(85,360),new GLatLng(-85,360)],null,0,0,"#000",0.4);

    /* Add Loading Overlays */
    $loader.show = function () {
        var i = 0, len = $loader.overlays.length;
        while (i < len) {
            gmap.addOverlay($loader.overlays[i]);
            i++;
        }
    }

    /* Remove Loading Overlays */
    $loader.hide = function () {
        var i = 0, len = $loader.overlays.length;
        while (i < len) {
            gmap.removeOverlay($loader.overlays[i]);
            i++;
        }
    }

}

/* Save Map State to Cookie */
function mapSave () {
    var mapzoom   = gmap.getZoom();
    var mapcenter = gmap.getCenter();
    var maplat    = mapcenter.lat();
    var maplng    = mapcenter.lng();
    var cookiestring = maplat + "_" + maplng + "_" + mapzoom;
    var exp = new Date(); //set new date object
    exp.setTime(exp.getTime() + (1000 * 60 * 60 * 24 * 30)); //set it 30 days ahead
    rew_setCookie(cookie_name, cookiestring, exp);
}

/* Load Map State from Cookie */
function mapRestore () {
    var loadedstring = rew_getCookie(cookie_name);
    var splitstr = loadedstring.split("_");
    if (splitstr != '') {
        gmap.setCenter(new GLatLng(parseFloat(splitstr[0]), parseFloat(splitstr[1])), parseFloat(splitstr[2]));
    }
}

/* Set Cookie */
function rew_setCookie (name, value, expires) {
    document.cookie = name + "=" + escape(value) + "; path=/" + ((expires == null) ? "" : "; expires=" + expires.toGMTString());
}

/* Get Cookie */
function rew_getCookie (c_name) {
    if (document.cookie.length > 0) {
        c_start = document.cookie.indexOf(c_name + "=");
        if (c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = document.cookie.indexOf(";", c_start);
            if (c_end == -1) c_end = document.cookie.length;
            return unescape(document.cookie.substring(c_start, c_end));
        }
    }
    return "";
}
