function MapDisplay(workout_track_loader, route_id, map_div_id) {
	this.loader = workout_track_loader;
	this.map_id = map_div_id;
	this.map = null;
	this.routeLayer;
	this.routeID;
	this.num_tries = 0;
	this.mmfMapOptions = {};
	this.mmfMapOptionsCookie = $.cookies.get('mmf_map_options');
	this.watching_video = false;

	this.trafficMapType;
	this.osmMapType;

	this.gmapLayersApplied = [];
	
	this.routeID = route_id;

	if (this.mmfMapOptionsCookie !== null) {
	    this.mmfMapOptions = $.cookies.get('mmf_map_options');
	} else {
            this.mmfMapOptions = {"map_type": "street", "show_distance_markers": false, "show_route_markers": true, "show_bike_paths": false};
	}

    // Get Location Center Point - Center on Route Start Points
    // Map recenters on kml file after load, but this keeps from crazy panning
	if (this.routeID != null) {
            this.myLatlng = new google.maps.LatLng(_MMF_GLOBAL.rd.route_center_lat, _MMF_GLOBAL.rd.route_center_lng);
	} else {
            this.myLatlng = null;
	}

    // Extend Layers
    this.MAPTYPE_OSM = "OSM";
    this.osmMapType = new google.maps.ImageMapType({
	    getTileUrl: function(coord, zoom) {
	        return "http://tile.openstreetmap.org/" +
	        zoom + "/" + coord.x + "/" + coord.y + ".png";
	    },
	    tileSize: new google.maps.Size(256, 256),
	    isPng: true,
	    alt: "OpenStreetMap layer",
	    name: "OpenStreetMap",
	    maxZoom: 19
	});
    
    this.MAPTYPE_TRAFFIC = "traffic";
    this.trafficMapType = new google.maps.ImageMapType({
      getTileUrl: function(coord, zoom) {
        return "http://mt3.google.com/mapstt?" +
        "zoom=" + zoom + "&x=" + coord.x + "&y=" + coord.y + "&client=api";
      },
      maxZoom: 19,
      tileSize: new google.maps.Size(256, 256),
      isPng: true,
      alt: "Traffic",
      name: "Traffic"
    });

    this.mapTypes = new Array();
    this.mapTypes.push(google.maps.MapTypeId.HYBRID);
    this.mapTypes.push(google.maps.MapTypeId.ROADMAP);
    this.mapTypes.push(google.maps.MapTypeId.SATELLITE);
    this.mapTypes.push(google.maps.MapTypeId.TERRAIN);
    //this.mapTypes.push(MAPTYPE_TRAFFIC);
    //this.mapTypes.push(MAPTYPE_OSM);
	

    // Set Map Options and Defaults
    this.mapOptions = {
        zoom: 12,
        center: this.myLatlng,
        mapTypeControl: false,
        panControl: false,
        panControlOptions: {
            position: google.maps.ControlPosition.LEFT_BOTTOM
        },
        streetViewControl: true,
        scrollwheel: false,
        mapTypeControlOptions: {
            style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
            mapTypeIds: this.mapTypes
        },
        scaleControl: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    if ( $.browser.webkit && !$.browser.opera && !$.browser.msie && !$.browser.mozilla ) {

        var userAgent = navigator.userAgent.toLowerCase();

        if ( userAgent.indexOf("chrome") === -1 ) {
            //alert("safari");
            // Add google panning control
            this.mapOptions.panControl = true;

        }
    }
	    
	this.displayMap = function() {
            // Build the Map
	    this.map = new google.maps.Map(document.getElementById(this.map_id), this.mapOptions);
	    this.bikeLayer = new google.maps.BicyclingLayer();
	    this.map.mapTypes.set(this.MAPTYPE_OSM, this.osmMapType);
	    this.map.mapTypes.set(this.MAPTYPE_TRAFFIC, this.trafficMapType);

	    // Set intial optionsq
            this.SetInitialMenuDisplay();

	    // Overlay KML File for Route
	    this.updateKML();
	    
	    var that = this;
	    // Overlay workout track
	    if (this.loader != null && this.loader.hasGeoData) {
			$.each(this.loader.lapPolylines, function(i,v) {
	    		this.setMap(that.map);
	         });
	    }
	    this.recenter_map();

	    $(".mmf_3d_icon, #recenter_map, #bike_layer_btn, #full_size_map").show();

	    $("#recenter_map").bind("click", function() {
	        that.recenter_map();
	    });

	    $(".climb_data_link").live("click", function(){
	        // Get Tabs ID
	        var $tabs = $(".mmf_tabs").tabs();
	        $tabs.tabs('select',1);
	    });

	    $("#full_size_map").bind("click", function() {
	        $(".mmf_edit_icon").trigger("click");
	    });

	    $("#watch_route_video_link, #watch_route_video_slide").bind("click", function() {
	        that.watchRouteVideo(that.routeID);
	    });

	    $('#watch_route_video_link')
		.mouseover(function(){
	            $(".watch_video_icon").fadeOut();
	            $("#watch_route_video_slide").stop().animate({width:"128px"}, 500).mouseout(function(){
	                $("#watch_route_video_slide").stop().animate({width:"12px"});
	                $(".watch_video_icon").fadeIn();
	            });
	    });
	    $('#full_size_map')
		.mouseover(function(){
	            $("#full_size_icon_slide").stop().animate({width:"109px"}, 500);
	    }).mouseout(function(){
	                $("#full_size_icon_slide").stop().animate({width:"12px"});
	            });
		

	    // Make Tooltip for each climb icon
	    $(".mmf_climb_item, .mmf_climb_info").each(function(){

	        var content = $(this).children(".mmf_climb_hover").html();

	        $(this).qtip({
	            content: content,
	            style: {
	                tip: 'bottomMiddle',
	                width:350,
	                border: {width: 7, radius: 3, color: '#3D3D3D'}
	            },
	            show: {
	                solo:true,
	                when: {event: 'mouseover'}
	            },
	            hide: {
	                delay: 1700,
	                when: {event: 'mouseout'}
	            },
	            position: {
	              corner: {
	                 target: 'topMiddle',
	                 tooltip: 'bottomMiddle'
	              }
	           }
	        });
	    });
	    
	    this.OptionsMenuInvoker();
	};

	this.setDefaultSearch = function() {
	   $.cookies.set("mmf_map_options", this.mmfMapOptions, {expires: 90, path: '/'});
	   $("#default_options_link_set").text("Saved as default options");
	};
	this.resetDefaultSearch = function() {
	    $.cookies.del("mmf_map_options");
	    $("#default_options_link_reset").text("Options Reset");
	    this.mmfMapOptions = {"map_type": "street", "show_distance_markers": true, "show_route_markers": true, "show_bike_paths": false};
	    this.changeMapType(this.mmfMapOptions.map_type);
	    this.showbikeLayer(this.mmfMapOptions.show_bike_paths, true);
	    this.showDistanceMarkers(this.mmfMapOptions.show_route_markers, true);
	    this.showRouteMarkers(this.mmfMapOptions.show_distance_markers, true);
	};


	// Start Functions
	this.recenter_map = function() {
		if (this.loader != null && this.loader.hasGeoData) {
			this.map.fitBounds(this.loader.bounds);
		} else if (this.routeLayer != null && this.routeLayer.getDefaultViewport() != null) {
			this.map.fitBounds(this.routeLayer.getDefaultViewport());
		}
	};

	this.showbikeLayer = function(showhide, initial) {
	    if (showhide === true) {
	        // Add Bike Layer
	        this.bikeLayer.setMap(this.map);
	        this.mmfMapOptions.show_bike_paths = true;
	        $("#bike_layer_options_show").addClass("opt_on");
	        $("#bike_layer_options_hide").removeClass("opt_on");
	    } else {
	        // Hide Bike Layer
	        this.bikeLayer.setMap(null);
	        this.mmfMapOptions.show_bike_paths = false;
	        $("#bike_layer_options_hide").addClass("opt_on");
	        $("#bike_layer_options_show").removeClass("opt_on");
	    }
	    if (initial !== true) {
	        this.updateKML();
	    }
            this.SetMapOptionsCookie();
	};

	this.showDistanceMarkers = function (showhide, initial) {
	    if (showhide === true) {
	        this.mmfMapOptions.show_distance_markers = true;
	        $("#distance_marker_options_show").addClass("opt_on");
	        $("#distance_marker_options_hide").removeClass("opt_on");
	    } else {
	    	this.mmfMapOptions.show_distance_markers = false;
	        $("#distance_marker_options_hide").addClass("opt_on");
	        $("#distance_marker_options_show").removeClass("opt_on");
	    }

	    if (initial !== true) {
	        this.updateKML();
	    }
            this.SetMapOptionsCookie();
	};

	this.showRouteMarkers = function (showhide, initial) {
	    if (showhide === true) {
	    	this.mmfMapOptions.show_route_markers = true;
	        $("#route_marker_options_show").addClass("opt_on");
	        $("#route_marker_options_hide").removeClass("opt_on");
	    } else {
	    	this.mmfMapOptions.show_route_markers = false;
	        $("#route_marker_options_hide").addClass("opt_on");
	        $("#route_marker_options_show").removeClass("opt_on");
	    }

	    if (initial !== true) {
	        this.updateKML();
	    }
            this.SetMapOptionsCookie();
	};

        this.SetMapOptionsCookie = function () {
            $.cookies.set("mmf_map_options", this.mmfMapOptions, {expires: 90, path: '/'});
        };

        this.SetInitialMenuDisplay = function () {
            this.changeMapType(this.mmfMapOptions.map_type);

            if (this.mmfMapOptions.show_route_markers === true) {
                $("#route_marker_options_show").addClass("opt_on");
	        $("#route_marker_options_hide").removeClass("opt_on");
            } else {
                $("#route_marker_options_hide").addClass("opt_on");
	        $("#route_marker_options_show").removeClass("opt_on");
            }
            if (this.mmfMapOptions.show_distance_markers === true) {
	        $("#distance_marker_options_show").addClass("opt_on");
	        $("#distance_marker_options_hide").removeClass("opt_on");
            } else {
                $("#distance_marker_options_hide").addClass("opt_on");
	        $("#distance_marker_options_show").removeClass("opt_on");
            }
            if (this.mmfMapOptions.show_bike_paths === true) {
	        $("#bike_layer_options_show").addClass("opt_on");
	        $("#bike_layer_options_hide").removeClass("opt_on");
            } else {
                $("#bike_layer_options_hide").addClass("opt_on");
	        $("#bike_layer_options_show").removeClass("opt_on");
            }
        }
		
	this.updateKML = function () {
	    var last_updated = escape(new Date().getTime());
		
		// Distance Between Markers, let KML Generator Auto-Calculate 
	    var marker_interval = 1000;
		if(_MMF_GLOBAL.units.distance == 'mi') {
	         marker_interval = 1609;
	    }

	    if (typeof this.routeLayer !== 'undefined') {
	        this.routeLayer.setMap(null);
	    }
	    
	    var kml_url = _MMF_GLOBAL.api.server + _MMF_GLOBAL.api.url4 + "routes/get_route_kml?consumer_key=" + _MMF_GLOBAL.api.key + "&route_id="+this.routeID;
	    // Local testing kml_url below
//		    var kml_url = "http://prod.panama.mapmyfitness.com/ws/4p/routes/get_route_kml?consumer_key=" + _MMF_GLOBAL.api.key + "&route_id="+50671182;
//		    var kml_url = "http://qa.panama.mapmyfitness.com/artur-proxy/api-panama/PanamaChangesLive/public/routes/get_route_kml?consumer_key=" + _MMF_GLOBAL.api.key + "&route_id="+route_id;
	    //var kml_url = "http://dl.dropbox.com/u/7103956/ferry_building_route.kml";
		
	    if (this.mmfMapOptions.show_route_markers === true) {
	        kml_url = kml_url + "&display_custom_marker_flag=1"
	    }
		
	    if (this.mmfMapOptions.show_distance_markers === true) {
	        kml_url = kml_url + "&display_distance_marker_flag=1&display_distance_marker_auto=1&display_marker_interval=" + marker_interval;
	    }

	    kml_url = kml_url + "&last_updated=" + last_updated;

		    //console.log(kml_url);

	    this.routeLayer = new google.maps.KmlLayer(kml_url, { map: this.map, suppressInfoWindows: true } );
	};

	this.resetGmapLayers = function() {
	    for (var i = 0; i < this.gmapLayersApplied.length; i++) {
	        this.map.overlayMapTypes.removeAt(0, this.gmapLayersApplied[i]);
		}
		this.gmapLayersApplied = [];
	};

	this.changeMapType = function(map_type) {

            $(".map_type .map_options li").removeClass("opt_on");
	    $(".map_type .map_switch_" + map_type).parent("li").addClass("opt_on");
	    this.mmfMapOptions.map_type = map_type;
	    
            this.resetGmapLayers();
		
	    switch(map_type) {
	        case "satellite":
	            this.map.setMapTypeId(google.maps.MapTypeId.SATELLITE);
	            break;
	        case "hybrid":
	            this.map.setMapTypeId(google.maps.MapTypeId.HYBRID);
	            break;
	        case "openstreet":
	            this.map.setMapTypeId("OSM");
	            break;
	        case "street":
	            this.map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
	            break;
	        case "terrain":
	            this.map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
	            break;
	        case "traffic":
	            this.map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
				this.map.overlayMapTypes.insertAt(0, trafficMapType);
				this.gmapLayersApplied.push(trafficMapType);
	            break;
	        default:
	            this.map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
	    }
	};
		
	// Responsible for initializing the ... Top Menu
	this.hideOptionsMenu = function () {
            $(".top_tools_btn").hide();
            $(".top_tools").hide();
	};

	this.OptionsMenuInvoker = function (element) {
	    this.waitingForExpand = false;
	    var self = this;

	    $(".top_tools_btn .mmf_expand").bind("click", function () {
	        if (self.waitingForExpand) {
                    return;
	        }

	        if ($(this).parent().hasClass("mmf_expanded")) {
	            self.waitingForExpand = true;
	            $(".top_tools .expand_content").slideToggle(function(){
	                $(".top_tools_btn").removeClass("mmf_expanded");
	                $(".top_tools").hide();
	                self.waitingForExpand = false;
	            });
	        } else {
	            self.waitingForExpand = true;
	            $(".top_tools_btn").addClass("mmf_expanded");
	            /*$(".top_tools").css("padding", "3px");*/
	            $(".top_tools").show();
	            $(".top_tools .expand_content").slideToggle();
	            self.waitingForExpand = false;
	        }

	    });
	};

	this.watchRouteVideo = function (route) {

	    if (this.watching_video !== true) {
                $('.ad_bg_300x250').hide();
                $('#header_banner_ad').hide();
	        this.watching_video = true;

	        var dialog_loaded = false;

	        // Google Earth Video player
	        var that = this;
	        var $dialog = $('<div id="watch_route_video_dialog"></div>')
	                .dialog({
	                    autoOpen: false,
	                    modal: true,
	                    height:600,
	                    width:640,
	                    zIndex: 9999,
	                    title: 'Course Fly-By Video',
	                    close: function(){
	                        $(this).remove();
	                        that.watching_video = false;
                            $('.ad_bg_300x250').show();
                            $('#header_banner_ad').show();
	                    }
	                });
	                $dialog.load("/routes/video/"+route, function(){
	                    $dialog.dialog('open');
	                });
	    }

	};
}

function load_video(url) {
    $("#player_api").hide();
    $("#advert_video").hide();
    $("#video_iframe").show();
    $("#video_iframe").attr("src", url);
}

