/**

Author        : Jeff Conklin (jeffconklin.com)
Script Name   : mappoint_maps_v0-3-6.js
Parent Module : mappoints::mapPoints (mPoint::v0.3)
Verson        : 0.3.6
Updated       : 12/28/2010

Usage / Public Calls

// Object Based interaction
var mapObj = new gMapInteraction({});

// Set Map ID. Should be the ID of the container where the map will be displayed. Will
//  only work if the map has not yet been loaded.
mapObj.map_Methods_Set_MapID("my-map-area_1");

// Set Map Type/Style. Expects: (ROADMAP) | SATELLITE | HYBRID | TERRAIN
mapObj.map_Methods_Set_MapTypeId("HYBRID");

// Set Type Navigation Control Style. Expects: SMALL | ZOOM_PAN | ANDROID | (DEFAULT)
mapObj.map_Methods_Set_NavigationControlStyle("DEFAULT");

// Set Type Control Bar. Expects: HORIZONTAL_BAR | DROPDOWN_MENU | (DEFAULT)
mapObj.map_Methods_Set_MapControlType("DROPDOWN_MENU");

// Set the lat and lon of the map center. Expects: Number, 1-20
// Ex: mapObj.map_Methods_Set_MapZoom(14);
mapObj.map_Methods_Set_MapZoom(14);

// Set the lat and lon of the map center. Expects: lat, lon
mapObj.map_Methods_Set_MapCenter(40.3199,-74.0671);

// Traffic Layer
//  * When map is *not* loaded: Calls will set the layer on or off when map loads
//  * When map is loaded: Will either turn on, off, or toggle traffic layer
// Examples: mapObj.toggle_TrafficLayer();
//           mapObj.turnOff_TrafficLayer();
//           mapObj.turnOn_TrafficLayer();
mapObj.turnOff_TrafficLayer();

//  * When map is *not* loaded: Calls will set the bike layer on or off when map loads
//  * When map is loaded: Will either turn on, off, or toggle bike layer
// Examples: mapObj.toggle_BicyclingLayer();
//           mapObj.turnOff_BicyclingLayer();
//           mapObj.turnOn_BicyclingLayer();
mapObj.turnOff_BicyclingLayer();

// Add a marker
mapObj.markers_AddOne({
                        "title"                 : 'A marker for the system',
                        "lat"                   : 40.3126,
                        "lon"                   : -74.1392,
                        "clickable"             : true,
                        "draggable"             : true,
                        "infoWindow_content"    : "I like content. But how does this look with two windows?",
                        "dragEndCallback"       : {
                            "callFunction"      : updateFormFiendsWithLatLonZoom,
                            "additionalData"    : {
                                "form_field_id_lat"   : "latitude",
                                "form_field_id_lon"   : "longitude",
                                "form_field_id_zoom"  : "zoom"
                                }
                        }
                       });

// Calling this will aways show the info window, even when there is no content
mapObj.markers_AlwaysShowInfoWindow();




// Generate the map after the entire page has loaded
// Examples: mapObj.generateMap_OnLoad();
//           mapObj.generateMap_ShortDelay();
//           mapObj.generateMap();
mapObj.generateMap_OnLoad();



*/

/* Defaults: */
var default_marker_icon_id = -100000;
var default_marker_uid = -1;
var marker_icons = {
    "yellow"       : "http://maps.google.com/mapfiles/ms/micons/yellow-dot.png",
    "blue"         : "http://maps.google.com/mapfiles/ms/micons/blue-dot.png",
    "Exit"         : "http://maps.google.com/mapfiles/ms/micons/blue-dot.png",
    "red"          : "http://maps.google.com/mapfiles/ms/micons/red-dot.png",
    "Parking Area" : "http://maps.google.com/mapfiles/ms/micons/parkinglot.png"
}










gMapInteraction = Class.create();
Object.extend(gMapInteraction.prototype, {
    
    
    /*******************************************************************/
    /*******************       PUBLIC METHODS        *******************/
    
    initialize: function(rawData) {
        logInConsole("----------------------------");
        logInConsole("initialize called");
        
        if (typeof(rawData)!="undefined") rawData = { "map_info" : { "options" : {} } };
        
        // Initial/Default Data Setup
        this.data                       = {
            "_int"                      : {     // _int data holds internal / parsed data and is captured by the script. map_info is usually set onload
                "errors"                : {
                    "doNotRenderMap"    : 0
                },
                "counters"              : {
                    "markers"           : 0
                },
                "loaded_data"           : {
                    "loaded_markers"    : {}    // Will hold an associative array of markers that have been loaded. Structure: "40.2173|-74.4119" : 1
                },
                "raw_data"              : {
                    "raw_markers"       : []    // Will hold an array of raw marker data before system creates actual map points
                },
                "objects"               : {
                    "bikeLayer"         : {},
                    "infoWindow"        : {},
                    "mapObj"            : {},
                    "markers"           : [],
                    "traffic"           : 0
                },
                "flags"                 : {
                    "map_loaded"        : 0
                },
                "events"                : {
                    "map_events"        : []
                }
            },
            
            "map_info"                  : {     // Usually holds basic information before the maps are created and loaded
                "events"                : {},
                "map_center_lat"        : 40.2173,
                "map_center_lon"        : -74.4119,
                "map_zoom"              : 10,
                "map_id"                : "",
                "options"               : {
                    "MapTypeId"         : "ROADMAP", // SATELLITE | HYBRID | TERRAIN | (ROADMAP)
                    "MapTypeControlStyle" : "DEFAULT", // HORIZONTAL_BAR | DROPDOWN_MENU | (DEFAULT)
                    "navigationControl" : "DEFAULT",  // SMALL | ZOOM_PAN | ANDROID | (DEFAULT)
                    "addTrafficOnLoad"  : 0, // 1|0
                    "addBicyclingLayerOnLoad" : false  // true|false
                }
            }
        };
        
        // map info: Id
        if (rawData.map_info.map_id) this._data_GenMap_map_id(rawData.map_info.map_id);
        
        // map info: Lat / Lon
        if (rawData.map_info.map_center_lat) this._data_GenMap_Center_Lat(rawData.map_info.map_center_lat);
        if (rawData.map_info.map_center_lon) this._data_GenMap_Center_Lon(rawData.map_info.map_center_lon);
        
        // map info: Zoom
        if (rawData.map_info.map_zoom) this._data_GenMap_Zoom(rawData.map_info.map_zoom);
        
        // map options: map type ID         // SATELLITE | HYBRID | TERRAIN | (ROADMAP)
        if (rawData.map_info.options.MapTypeId) this.map_Methods_Set_MapTypeId(rawData.map_info.options.MapTypeId);
        
        // map options: type control bar    // HORIZONTAL_BAR | DROPDOWN_MENU | (DEFAULT)
        if (rawData.map_info.options.MapTypeControlStyle) this.map_Methods_Set_MapControlType(rawData.map_info.options.MapTypeControlStyle);
        
        // map options: navigation control style  // SMALL | ZOOM_PAN | ANDROID | (DEFAULT)
        if (rawData.map_info.options.navigationControl) this._data_MapOpts_NavCtrl(rawData.map_info.options.navigationControl);
        
        // map options: add traffic layer
        if (rawData.map_info.options.addTrafficOnLoad) this._data_MapOpts_Flag_AddTrafficLayerOnLoad(rawData.map_info.options.addTrafficOnLoad);
        
        // map options: add bike layer
        if (rawData.map_info.options.addBicyclingLayerOnLoad) this._data_MapOpts_Flag_AddBicyclingLayerOnLoad(rawData.map_info.options.addBicyclingLayerOnLoad);
        
        // map events
        if (rawData.map_info.events) this._events_Raw_SetAllRawEvents(rawData.map_info.events);
        
        // map markers
        //   COMING SOON
        
        //alert( this._objects_MapOpts_TrafficLayerObj() + "\n" + this.data._int.objects.traffic + "\n" + this.data._int.objects);
        
        
        
    },    // END initialize
    
    
    // This will load the map after the window has loaded completely
    generateMap_OnLoad: function() {
        logInConsole("generateMap_OnLoad called");
        Event.observe(window, 'load', this.generateMap.bind(this));
    },    // END generateMap_OnLoad
    
    // This will load the map after a short delay
    generateMap_ShortDelay: function() {
        logInConsole("generateMap_ShortDelay called");
        setTimeout(this.generateMap.bind(this),200);
    },    // END generateMap_OnLoad
    
    
    // This will load the map after a longer delay
    generateMap_LongerDelay: function() {
        logInConsole("generateMap_LongerDelay called");
        setTimeout(this.generateMap.bind(this),1000);
    },    // END generateMap_OnLoad
    
    // This will load the map later.
    generateMap_ONCLICKONLY: function() {
        logInConsole("generateMap_LongerDelay called");
        // setTimeout(this.generateMap.bind(this),1000);
    },    // END generateMap_OnLoad
    
    // This will create/display the map.
    generateMap: function() {
        logInConsole("----------------------------");
        logInConsole("generateMap called");
        
        if (this._data_GenMap_map_id().length < 1) {
            alert("You must specify a map_id. This should be the\nunique ID of an element within your HTML.")
            this._err_DoNotgenerateMap_On();
        } else {
            
            // Set basic options
            var myOptions2 = {
                zoom                : this._data_GenMap_Zoom(),
                center              : new google.maps.LatLng(this._data_GenMap_Center_Lat(),this._data_GenMap_Center_Lon()),
                mapTypeId           : this._data_MapOpts_MapType(),
                mapTypeControl      : false,
                navigationControl   : false
            };
            
            // Update the options: Nav Type
            if (this._data_MapOpts_MapControlType()) {
                myOptions2.mapTypeControl = true;
                myOptions2.mapTypeControlOptions = { style : this._data_MapOpts_MapControlType() };
            }
            
            // Update the options: Navigation Control
            if (this._data_MapOpts_NavCtrl()) {
                myOptions2.navigationControl = true;
                myOptions2.navigationControlOptions = { "style" : this._data_MapOpts_NavCtrl() };
            }
            
            // Create/Capture map object. Add Markers (if applicable)
            if (!this._err_DoNotgenerateMap_Check()) {
                
                // Create when no errors
                this.object_Map(new google.maps.Map($(this._data_GenMap_map_id()),myOptions2));
                
                // Creating an InfowWindow
                if (!this.myInfoWindow_Check()) {
                    this.myInfoWindow(new google.maps.InfoWindow({
                        content: 'Loading...'
                    }));
                }
                
                // Add Any Raw Markers added to the object
                if (this._markers_RawMarkers_HowMany()) this._markers_RawMarkers_AddAllToMap();
                
                // Add Traffic Overlay
                if (this._data_MapOpts_Flag_AddTrafficLayerOnLoad()) {
                    this.toggle_TrafficLayer();
                }
                
                // Add Bike Overlay
                if (this._data_MapOpts_Flag_AddBicyclingLayerOnLoad()) {
                    this.turnOn_BicyclingLayer();
                }
            
                // Delay the load of specific events until AFTER map has totally loaded
                google.maps.event.addListenerOnce(this.object_Map(), 'tilesloaded', (function(mapObj) { return function() {
            
                    // Add raw events to map
                    if (mapObj._events_Raw_RawEvents_HowMany()) { mapObj._events_Raw_AddAllToMap(); }
                    
                    // Close info window when another one is clicked.
                    google.maps.event.addListener(mapObj.object_Map(), 'click', (function(myInfoWindow) { return function() {
                        myInfoWindow.close();
                    }})(mapObj.myInfoWindow()));
                    
                }})(this));
                
            }
        
        // Hande everything when the page unloads
        //google.maps.event.addDomListener(window,'unload', google.maps.Unload() );
        Event.observe(window, 'unload', this.deather_To_The_Map.bind(this));
        
        }
        
    },    // END generateMap
    
    
    deather_To_The_Map : function() {
        //alert("Cya");
        this.data = {};
    },
    
    
    // **** Map Setup / Initialization ****
    
    // Set Map ID. Should be the ID of the container where the map will be displayed. Will
    //  only work if the map has not yet been loaded.
    // Ex: mapObj.map_Methods_Set_MapID("my-map-area_1");
    map_Methods_Set_MapID : function(mapId) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_MapID called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        
        if (!this.check_IsMapLoaded()) {
            this._data_GenMap_map_id(mapId);
        }
        
    },
    
    // Set the lat and lon of the map center. Expects: lat, lon
    // Ex: mapObj.map_Methods_Set_MapCenter(40.3199,-74.0671);
    map_Methods_Set_MapCenter : function(newLat,newLon) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_MapCenter called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        this._data_GenMap_Center_Lat(newLat)
        this._data_GenMap_Center_Lon(newLon)
        
        if (this.check_IsMapLoaded()) {
           this.object_Map().panTo( new google.maps.LatLng(this._data_GenMap_Center_Lat(),this._data_GenMap_Center_Lon()) );
        }
        
    },
    
    // Set the lat and lon of the map center. Expects: Number, 1-20
    // Ex: mapObj.map_Methods_Set_MapZoom(14);
    map_Methods_Set_MapZoom : function(zoomLevel) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_MapZoom called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        logInConsole("this._data_GenMap_Zoom() " + this._data_GenMap_Zoom() );
        this._data_GenMap_Zoom(zoomLevel);
        logInConsole("this._data_GenMap_Zoom() " + this._data_GenMap_Zoom() );
        
        if (this.check_IsMapLoaded()) {
            this.object_Map().setZoom(this._data_GenMap_Zoom());
        }
        
    },
    
    // Set Map Type/Style. Expects: (ROADMAP) | SATELLITE | HYBRID | TERRAIN
    // Ex: mapObj.map_Methods_Set_MapTypeId("HYBRID");
    map_Methods_Set_MapTypeId : function(newMapTypeId) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_MapTypeId called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        logInConsole("this._data_MapOpts_MapType() " + this._data_MapOpts_MapType() );
        this._data_MapOpts_MapType(newMapTypeId);
        logInConsole("this._data_MapOpts_MapType() " + this._data_MapOpts_MapType() );
        
        if (this.check_IsMapLoaded()) {
            this.object_Map().setMapTypeId(this._data_MapOpts_MapType());
        }
        
    },
    
    // Set Type Control Bar. Expects: HORIZONTAL_BAR | DROPDOWN_MENU | (DEFAULT)
    // Ex: mapObj.map_Methods_Set_MapControlType("DROPDOWN_MENU");
    map_Methods_Set_MapControlType : function(newMapCtrlTyp) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_MapControlType called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        logInConsole("newMapCtrlTyp: " + newMapCtrlTyp );
        
        logInConsole("this._data_MapOpts_MapControlType() " + this._data_MapOpts_MapControlType() );
        this._data_MapOpts_MapControlType(newMapCtrlTyp);
        logInConsole("this._data_MapOpts_MapControlType() " + this._data_MapOpts_MapControlType() );
        
        if (this.check_IsMapLoaded()) {
            this.object_Map().setOptions({ "mapTypeControl" : true, "mapTypeControlOptions" : { style : this._data_MapOpts_MapControlType() } });
        }
        
    },
    
    // Set Type Navigation Control Style. Expects: SMALL | ZOOM_PAN | ANDROID | (DEFAULT)
    // Ex: mapObj.map_Methods_Set_NavigationControlStyle("DEFAULT");
    map_Methods_Set_NavigationControlStyle : function(newNavCtrlStyle) {
        logInConsole("*************************************************");
        logInConsole("map_Methods_Set_NavigationControlStyle called");
        logInConsole("Is Map Loaded Yet? " + this.check_IsMapLoaded() );
        logInConsole("newNavCtrlStyle: " + newNavCtrlStyle );
        
        logInConsole("this._data_MapOpts_NavCtrl() " + this._data_MapOpts_NavCtrl() );
        this._data_MapOpts_NavCtrl(newNavCtrlStyle);
        logInConsole("this._data_MapOpts_NavCtrl() " + this._data_MapOpts_NavCtrl() );
        
        if (this.check_IsMapLoaded()) {
            this.object_Map().setOptions({ "navigationControl" : true, "navigationControlOptions" : { "style" : this._data_MapOpts_NavCtrl() } });
        }
        
    },
    
    
    
    // **** Traffic Layer ****
    //  * When map is *not* loaded: Calls will set the layer on or off when map loads
    //  * When map is loaded: Will either turn on, off, or toggle traffic layer
    // Ex: mapObj.toggle_TrafficLayer();
    // Ex: mapObj.turnOff_TrafficLayer();
    // Ex: mapObj.turnOn_TrafficLayer();
    turnOff_TrafficLayer : function()   {
        logInConsole(" -- turnOff_TrafficLayer called");
        if (!this.check_IsMapLoaded()) {
            this._data_MapOpts_Flag_AddTrafficLayerOnLoad(false);
        } else {
            if (this._data_MapOpts_Flag_AddTrafficLayer()) {
                if (!this._objects_MapOpts_TrafficLayerObj()) this._objects_Create_TrafficLayerObj();
                if (this.check_IsMapLoaded()) {
                    logInConsole("     -- Actually Hiding Layer");
                    this._objects_TurnOff_TrafficLayer();
                }
            }
        }
    },
    turnOn_TrafficLayer : function()   {
        logInConsole(" -- turnOn_TrafficLayer called");
        if (!this.check_IsMapLoaded()) {
            this._data_MapOpts_Flag_AddTrafficLayerOnLoad(true);
        } else {
            if (!this._data_MapOpts_Flag_AddTrafficLayer()) {
                if (!this._objects_MapOpts_TrafficLayerObj()) this._objects_Create_TrafficLayerObj();
                if (this.check_IsMapLoaded()) {
                    logInConsole("     -- Actually Showing Layer");
                    this._objects_TurnOn_TrafficLayer();
                }
            }
        }
    },
    toggle_TrafficLayer : function() {
        logInConsole(" -- toggle_TrafficLayer called");
        if (!this.check_IsMapLoaded()) {
            if (this._data_MapOpts_Flag_AddTrafficLayerOnLoad()) this._data_MapOpts_Flag_AddTrafficLayerOnLoad(false);
            else                                                 this._data_MapOpts_Flag_AddTrafficLayerOnLoad(true);
        } else {
            if (!this._objects_MapOpts_TrafficLayerObj()) this._objects_Create_TrafficLayerObj();
            
            if (this._data_MapOpts_Flag_AddTrafficLayer()) {
                logInConsole("     -- Actually Hiding Layer");
                this._objects_TurnOff_TrafficLayer();
            } else {
                logInConsole("     -- Actually Showing Layer");
                this._objects_TurnOn_TrafficLayer();
            }
        
        }
    },
    
    
    
    
    // **** Bicycling Layer ****
    //  * When map is *not* loaded: Calls will set the bike layer on or off when map loads
    //  * When map is loaded: Will either turn on, off, or toggle bike layer
    // Ex: mapObj.toggle_BicyclingLayer();
    // Ex: mapObj.turnOff_BicyclingLayer();
    // Ex: mapObj.turnOn_BicyclingLayer();
    turnOff_BicyclingLayer : function()   {
        logInConsole(" -- turnOff_BicyclingLayer called");
        if (!this.check_IsMapLoaded()) {
            this._data_MapOpts_Flag_AddBicyclingLayerOnLoad(false);
        } else {
            if (this._data_MapOpts_Flag_AddBicyclingLayer()) {
                if (!this._objects_MapOpts_BicyclingLayerObj()) this._objects_Create_BicyclingLayerObj();
                if (this.check_IsMapLoaded()) {
                    logInConsole("     -- Actually Hiding Layer");
                    this._objects_TurnOff_BicyclingLayer();
                }
            }
        }
    },
    turnOn_BicyclingLayer : function()   {
        logInConsole(" -- turnOn_BicyclingLayer called");
        if (!this.check_IsMapLoaded()) {
            this._data_MapOpts_Flag_AddBicyclingLayerOnLoad(true);
        } else {
            if (!this._data_MapOpts_Flag_AddBicyclingLayer()) {
                if (!this._objects_MapOpts_BicyclingLayerObj()) this._objects_Create_BicyclingLayerObj();
                if (this.check_IsMapLoaded()) {
                    logInConsole("     -- Actually Showing Layer");
                    this._objects_TurnOn_BicyclingLayer();
                }
            }
        }
    },
    toggle_BicyclingLayer : function() {
        logInConsole(" -- toggle_BicyclingLayer called");
        if (!this.check_IsMapLoaded()) {
            if (this._data_MapOpts_Flag_AddBicyclingLayerOnLoad()) this._data_MapOpts_Flag_AddBicyclingLayerOnLoad(false);
            else                                                   this._data_MapOpts_Flag_AddBicyclingLayerOnLoad(true);
        } else {
            if (!this._objects_MapOpts_BicyclingLayerObj()) this._objects_Create_BicyclingLayerObj();
            
            if (this._data_MapOpts_Flag_AddBicyclingLayer()) {
                logInConsole("     -- Actually Hiding Layer");
                this._objects_TurnOff_BicyclingLayer();
            } else {
                logInConsole("     -- Actually Showing Layer");
                this._objects_TurnOn_BicyclingLayer();
            }
        
        }
    },

    
    
    
    
    
    

    // **** Map Interaction ****
    map_GetBounds : function() {
        return [this.object_Map().getBounds().getNorthEast().lat(),
                this.object_Map().getBounds().getNorthEast().lng(),
                this.object_Map().getBounds().getSouthWest().lat(),
                this.object_Map().getBounds().getSouthWest().lng()
               ];
    },
    map_GetBounds_Lat_Top   : function() { return this.object_Map().getBounds().getNorthEast().lat(); },
    map_GetBounds_Lat_Bot   : function() { return this.object_Map().getBounds().getSouthWest().lat(); },
    map_GetBounds_Lon_Right : function() { return this.object_Map().getBounds().getNorthEast().lng(); },
    map_GetBounds_Lon_Left  : function() { return this.object_Map().getBounds().getSouthWest().lng(); },
    
    map_GetCenter : function() {
        return [this.object_Map().getCenter().lat(),
                this.object_Map().getCenter().lng()
               ];
    },
    map_GetCenter_Lat   : function() { return this.object_Map().getCenter().lat(); },
    map_GetCenter_Lon   : function() { return this.object_Map().getCenter().lng(); },

    
    
    
    
    
    
    // **** Geneal Event Handling ****
    map_Event_Resize : function()   {
        google.maps.event.trigger(this.object_Map(), "resize");
    },
    
    _events_Raw_RawEvents_HowMany : function()   {
        var count = 0; for (var i in this.data.map_info.events) { count++; } return count;
    },
    _events_Raw_SetAllRawEvents : function()   {
        if (arguments.length) this.data.map_info.events = arguments;
    },
    _events_Raw_SetOneRawEvents : function(eventName,eventData)   {
        if (arguments.length) this.data.map_info.events[eventName] = eventData;
    },
    _events_Raw_GetAllRawEvents : function()   {
        return this.data.map_info.events;
    },
    _events_Raw_GetOneRawEvents : function(eventName)   {
        if (this.data.map_info.events[eventName]) return this.data.map_info.events[eventName]; else return 0;
    },
    _events_Raw_CheckOneRawEvents : function(eventName)   {
        if (this.data.map_info.events[eventName]) return 1; else return 0;
    },
    _events_Raw_AddAllToMap : function() {
        logInConsole("_events_Raw_AddAllToMap called");
        if (this._events_Raw_RawEvents_HowMany()) {
            
            for (var iEvent in this.data.map_info.events) {
                switch(iEvent) {
                    case 'dragMapEndCallback' : this._attachEvent__Map_Pan_DragEnd(this.data.map_info.events[iEvent]);
                    break;
                    case 'dragZoomEndCallback' : this._attachEvent__Map_Zoom_End(this.data.map_info.events[iEvent]);
                    break;
                    case 'onLoad_Markers_Add_To_Map' : this._attachOnload__Markers_Add_To_Map(this.data.map_info.events[iEvent]);
                    break;
                    case 'onLoad_Markers_Add_To_Map_Alt' : this._attachOnload__Markers_Add_To_Map(this.data.map_info.events[iEvent]);
                    break;
                    default : logInConsole("_events_Raw_AddAllToMap -- : -- default Case Called");
                }
            }
        } // END - if (this._events_Raw_RawEvents_HowMany()) {
    }, // END - _events_Raw_AddAllToMap
    
    
    _events_Redraw_Map : function() {
        logInConsole(' ** _events_Redraw_Map Called!');
        google.maps.event.trigger(this.object_Map(), "resize");
        // gmap.setCenter(gmlatlng);
    }, // END - _events_Redraw_Map
    
    
    
    
    
    // On Map Load, we should add all the current points to the map. You can specify limitations.
    onLoad_Markers_Add_To_Map_Alt : function() {
        this.onLoad_Markers_Add_To_Map(arguments[0],'ALT');
    },
    onLoad_Markers_Add_To_Map : function() {
        logInConsole("onLoad_Markers_Add_To_Map called ---- "+arguments[1]);
        
        var addName = '';
        if (arguments[1]) addName = '_Alt';
        this._events_Raw_SetOneRawEvents('onLoad_Markers_Add_To_Map'+addName,arguments[0]);
        
        if (!this.check_IsMapLoaded()) { /* Do nothing */ logInConsole(" - Map Not Loaded"); }
        else {
            logInConsole(" - Loading Now" + this._checkEvent_onLoad_Markers_Add_To_Map());
            if (this._checkEvent_onLoad_Markers_Add_To_Map()) this._events_Raw_AddAllToMap();
        }
    },
    _attachOnload__Markers_Add_To_Map : function(additionalInformation) {
        logInConsole("_attachOnload__Markers_Add_To_Map called");
        interact_With_MapPoint_BackEnd(this,additionalInformation);
    },
    _checkEvent_onLoad_Markers_Add_To_Map : function() { return this._events_Raw_CheckOneRawEvents('onLoad_Markers_Add_To_Map'); },
    
    
    
    
    
    // Add a Map Dragend callback function. First it'll add the passed
    //  arg to the general events container. Then it'll check to see if
    //  the map is loaded. If the map has loaded, it'll call the proper
    //  function that will attach all the events to map.
    addEvent_Map_Pan_DragEnd : function() {
        logInConsole("addEvent_Map_Pan_DragEnd called");
        this._events_Raw_SetOneRawEvents('dragMapEndCallback',arguments[0]);
        if (!this.check_IsMapLoaded()) { /* Do nothing */ }
        else {
            if (this._checkEvent_Map_Pan_DragEnd()) this._events_Raw_AddAllToMap();
        }
    },
    _attachEvent__Map_Pan_DragEnd : function(additionalInformation) {
        logInConsole("_attachEvent__Map_Pan_DragEnd called");
        
        if (additionalInformation.defaultFunction) {
            google.maps.event.addListener(this.object_Map(), 'dragend', (function(mapObj,additionalInformation) { return function() {
                map_Pan_Drag_End_Interaction(mapObj,additionalInformation);
            }})(this,additionalInformation));
        } else {
            google.maps.event.addListener(this.object_Map(), 'dragend', (function(mapObj,additionalInformation) { return function() {
                additionalInformation.callFunction(mapObj,additionalInformation);
            }})(this,additionalInformation));
        }
        
    },
    _checkEvent_Map_Pan_DragEnd : function() { return this._events_Raw_CheckOneRawEvents('dragMapEndCallback'); },
    
    
    
    
    
    // Add a Map Zoom callback function. 
    addEvent_Map_Zoom_End : function() {
        logInConsole("~~~~~~~~~ addEvent_Map_Zoom_End called");
        this._events_Raw_SetOneRawEvents('dragZoomEndCallback',arguments[0]);
        if (!this.check_IsMapLoaded()) { /* Do nothing */ }
        else {
            if (this._checkEvent_Map_Zoom_End()) this._events_Raw_AddAllToMap();
        }
    },
    _attachEvent__Map_Zoom_End : function(additionalInformation) {
        logInConsole("@@@@@@@@@ _attachEvent__Map_Pan_DragEnd called");
        
        if (additionalInformation.defaultFunction) {
            google.maps.event.addListener(this.object_Map(), 'zoom_changed', (function(mapObj,additionalInformation) { return function() {
                map_Zoom_End_Interaction(mapObj,additionalInformation);
            }})(this,additionalInformation));
        } else {
            google.maps.event.addListener(this.object_Map(), 'zoom_changed', (function(mapObj,additionalInformation) { return function() {
                additionalInformation.callFunction(mapObj,additionalInformation);
            }})(this,additionalInformation));
        }
        
    },
    _checkEvent_Map_Zoom_End : function() { return this._events_Raw_CheckOneRawEvents('dragZoomEndCallback'); },
    
    
    
    
    
    
    
    
    // **** Marker Interaction ****
    /** The following functions deal with markers. There are only a few public methods:
      * - markers_AddOne : This will collect the Raw Marker data set, and either collect the marker data when the map is not yet loaded,
      * or actually load the point onto the map.
      */
    markers_AddOne : function()   {
        logInConsole(" -- markers_AddOne called");
        
        this._markers_RawMarkers_CollectOne(arguments[0]);
        
        // has the map lodaed?
        if (!this.check_IsMapLoaded()) {
            // Do nothing
        
        } else {
            // Add Any Raw Markers added to the object
            if (this._markers_RawMarkers_HowMany()) this._markers_RawMarkers_AddAllToMap();
            
        }
        
    },
    markers_AddGroup : function()   {
        logInConsole(" -- markers_AddGroup called");

        for(var i=0; i<arguments[0].length; i++){
            this._markers_RawMarkers_CollectOne(arguments[0][i]);
        }
        
        // has the map lodaed?
        if (!this.check_IsMapLoaded()) {
            // Do nothing
        
        } else {
            // Add Any Raw Markers added to the object
            if (this._markers_RawMarkers_HowMany()) this._markers_RawMarkers_AddAllToMap();
            
        }
        
        logInConsole("--------------------------------------------------------");
    },
    markers_AlwaysShowInfoWindow : function() {
        this.data._int.counters.markers_AlwaysShowInfoWin = 1;
    },
    markers_InfoWindow_CheckAlwaysShow : function() {
        if (this.data._int.counters.markers_AlwaysShowInfoWin) return 1;
        else                                                   return 0;
    },
    
    markers_4All_SetClickFunction : function()   {
        this.markers_4All_CalFunction(arguments[0]);
    },
    markers_4All_CalFunction : function()   {
        if (arguments.length) this.data._int.loaded_data.markers_CallFunction = arguments[0];
        return this.data._int.loaded_data.markers_CallFunction;
    },
    markers_4All_CalFunction_Check : function()   {
        if (this.data._int.loaded_data.markers_CallFunction.length) return 1;
        else                                                        return 0;
    },
    
    _markers_RawMarkers_AddAllToMap : function() {
        logInConsole("_markers_RawMarkers_AddAllToMap called");
        
        if (this._markers_RawMarkers_HowMany()) {
            
            for (i=0; i<=this._markers_RawMarkers_HowMany();i++) {
                
                var current_marker = this._markers_RawMarkers_ReturnAll()[i];
                
                if (typeof(current_marker)=="undefined") break;
                
                // Make sure the point has not already been loaded. This is done by
                // calling the _markers_Markers_HasThisBeenAdded function. If the
                // lat/lon combo you sent has already been onto the map, it will
                // not be loaded again.
                if (!this._markers_Markers_IDCollection_CheckIfMarkerHasBeenLoaded(current_marker.lat,current_marker.lon)) {
                    
                    logInConsole(" ** Actually Adding Marker To Map");
                    
                    var markerOptions = {
                        position        : new google.maps.LatLng(current_marker.lat,current_marker.lon),
                        map             : this.object_Map(),
                        overlay_type    : 'marker',
                        icon            : marker_icons.red,
                        icon_data       : {
                            icon_id     : default_marker_icon_id,
                            image       : marker_icons.red
                        }
                    };
                    
                    // Marker ID?
                    if (current_marker.uid) {
                        markerOptions.uid      = ''+current_marker.uid;
                        markerOptions.named_id = 'marker_UID__'+current_marker.uid;
                    } else {
                        markerOptions.uid      = ''+default_marker_uid;
                        markerOptions.named_id = 'marker_UID__'+current_marker.uid;
                        default_marker_uid--;
                    }
                    
                    // Add draggable
                    if (current_marker.draggable == 1 || current_marker.draggable == true || current_marker.draggable == 'true') markerOptions.draggable = true;
                    else if (current_marker.draggable == 0 || current_marker.draggable == false || current_marker.draggable == 'false') markerOptions.draggable = false;
                    
                    // Add clickable
                    if (current_marker.clickable == 1 || current_marker.clickable == true || current_marker.clickable == 'true') markerOptions.clickable = true;
                    else if (current_marker.clickable == 0 || current_marker.clickable == false || current_marker.clickable == 'false') markerOptions.clickable = false;
                    
                    // Add Drop Animation
                    if (current_marker.animation == 1) markerOptions.animation = google.maps.Animation.DROP;
                    else if (current_marker.animation == 'true') markerOptions.animation = google.maps.Animation.DROP;
                    
                    // Add icon
                    logInConsole(current_marker.icon);
                    if (current_marker.icon) {
                        markerOptions.icon           = current_marker.icon.image;
                        markerOptions.icon_data.icon = current_marker.icon.image;
                        if (current_marker.icon.shadow) {
                            markerOptions.shadow = current_marker.icon.shadow;
                            markerOptions.icon_data.shadow = current_marker.icon.shadow;
                        }
                        if (current_marker.icon.id) markerOptions.icon_data.id = current_marker.icon.id;
                        else                        default_marker_icon_id++;
                    } else {
                        default_marker_icon_id++;
                    }
                    
                    // Add URLs
                    if (current_marker.title) markerOptions.title = current_marker.title;
                    
                    // Add title
                    if (current_marker.title) markerOptions.title = current_marker.title;
                    if (current_marker.title_parent) markerOptions.title_parent = current_marker.title_parent;
                    
                    // Add url
                    if (current_marker.url) markerOptions.url = current_marker.url;
                    if (current_marker.url_parent) markerOptions.url_parent = current_marker.url_parent;
                    
                    // Add parent_uid
                    if (current_marker.parent_uid) markerOptions.parent_uid = current_marker.parent_uid;
                    
                    // Add Markr Description
                    markerOptions.content = current_marker.infoWindow_content;
                    
                    // Add raw/original data to object (if applicable)
                    if (current_marker.flag_holdOrigData) markerOptions.original_data = current_marker;

                    logInConsole('a *******************************************************');
                    logInConsole(markerOptions);
                    logInConsole(current_marker);
                    //logInConsole(current_marker.icon.image);
                    //logInConsole(markerOptions.icon);
                    //if (current_marker.icon.image) logInConsole(current_marker.icon.image);
                    logInConsole(markerOptions);
                    logInConsole('  -- '+current_marker.clickable);
                    logInConsole('  -- '+this.markers_InfoWindow_CheckAlwaysShow());
                    logInConsole('b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
                    
                    // Create / add new marker to object
                    this._markers_Markers_Objects_AddOne( new google.maps.Marker(markerOptions) );
                    
                    logInConsole("___________________________________________________________________________");
                        logInConsole("a:"+this.markers_InfoWindow_CheckAlwaysShow());
                        logInConsole("b:"+this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers]);
                        logInConsole("c:"+this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers].getClickable());
                        this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers].setClickable(true);
                        logInConsole("d:"+this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers].getClickable());
                        logInConsole("-----------");
                        logInConsole("g:"+current_marker.infoWindow_content);
                        logInConsole("h:"+this.markers_InfoWindow_CheckAlwaysShow());
                        logInConsole("===========");
                        
                    // Add listener - Info Window
                    if (current_marker.infoWindow_content || this.markers_InfoWindow_CheckAlwaysShow()) {
                        
                        this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers].setClickable(true);
                    
                        google.maps.event.addListener(this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers], 'click', (function(map,marker,myInfoWindow,myInfoWindow_Template,myInfoWindow_CalFunction) { return function() {
                            
                            // If openWindow is not set to true, why would we pop open the window?
                            var openWindow = 0;
                            
                            // Do some custom magic when myInfoWindow_CalFunction || myInfoWindow_Template is sent
                            if (myInfoWindow_CalFunction || myInfoWindow_Template) {
                                
                                // Basic vars
                                var builtContent = '';    var builtContent_CalFunc = 0;    var builtContent_Template = 0;
                                
                                // if myInfoWindow_CalFunction is passed, caller wants to bind the marker click to a function they created
                                if (myInfoWindow_CalFunction) {
                                    builtContent_CalFunc = myInfoWindow_CalFunction.callFunction(marker);
                                    if (builtContent_CalFunc) {
                                        builtContent = builtContent_CalFunc;
                                        openWindow = 1;
                                    }
                                }
                                
                                // if myInfoWindow_Template is passed, caller has created there own prototype template to be used in the infoWindow
                                if (myInfoWindow_Template) {
                                    builtContent_Template = myInfoWindow_Template.evaluate(marker);
                                    if (builtContent_Template) {
                                        builtContent += builtContent_Template;
                                        openWindow = 1;
                                    }
                                }
                                
                                // Set the data into the window.
                                if (builtContent) myInfoWindow.setContent(builtContent);
                            
                            // If nothing is passed, the infoWindow will contain the content of the marker
                            } else {
                                myInfoWindow.setContent(marker.content);
                                openWindow = 1;  // Always mark this true. Even if there is no content. Not sor any real reason, but because I said so.
                            }
                            
                            // Only pop open when openWindow is true
                            if (openWindow) myInfoWindow.open(map, marker);
                            
                        }})(this.object_Map(), this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers], this.myInfoWindow(), this.myInfoWindow_Template(), this.myInfoWindow_CalFunction()));
                    }   // END - Add listener - Info Window
                    
                    // Add listener - OnClick on marker
                    if (this.markers_4All_CalFunction()) {
                        
                        // Make sure the icon is clickable
                        this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers].setClickable(true);
                        
                        google.maps.event.addListener(this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers], 'click', (function(map,marker,markers_4All_CalFunction) { return function() {
                        
                            markers_4All_CalFunction.callFunction(marker);
                            
                        }})(this.object_Map(), this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers],this.markers_4All_CalFunction()));
                    }   // END - Add listener - OnClick on marker
                    
                    // If the marker has been set as draggable, and a dragEndCallback has been defined, bind this sheeit
                    if (current_marker.draggable && current_marker.dragEndCallback) {
                        google.maps.event.addListener(this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers], 'dragend', (function(map,fullMarker,markerEvent) { return function() {
                            markerEvent.callFunction(map,fullMarker,markerEvent.additionalData);
                        }})(this.object_Map(),this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers],current_marker.dragEndCallback));
                    }
                    
                    // Add lat/lon ID so the script knows that point has already been added.
                    if (!current_marker.doNotTrackLatLonID) this._markers_Markers_IDCollection_MarkMarkerAsLoaded(current_marker.lat,current_marker.lon)
                    
                    // Add one to the overall marker counter
                    this.data._int.counters.markers++;
                    
                    logInConsole(" ** Marker Added");
                    
                }  // END-- if (!this._markers_Markers_IDCollection_CheckIfMarkerHasBeenLoaded(current_marker.lat,current_marker.lon)) {
                
            }  // END-- for (i=0; i<=this._markers_RawMarkers_HowMany();i++) {
            
            // Clear out the list when done looping
            this._markers_RawMarkers_ClearList();
            
        }
        
    },
    _markers_RawMarkers_AddOne : function() {
        logInConsole("_markers_RawMarkers_AddOne called");
        
        
    },
    
    // Marker object container
    _markers_Markers_Objects_AddOne : function()   {
        this.data._int.objects.markers.push(arguments[0]);
    },
    _markers_Markers_Objects_GetAll : function()   {
        return this.data._int.objects.markers;
    },
    _markers_Markers_Objects_ClearAll : function()   {
        this.data._int.objects.markers = [];
    },
    
    
    
    // Marker ID lists. Based on a Lat/Lon pair
    _markers_Markers_IDCollection_MarkMarkerAsLoaded : function(lat,lon)   {
        this.data._int.loaded_data.loaded_markers[lat+"|"+lon] = 1;
    },
    _markers_Markers_IDCollection_CheckIfMarkerHasBeenLoaded : function(lat,lon)   {
        //logInConsole("Lat/Lon Check: "+this.data._int.loaded_data.loaded_markers[lat+"|"+lon]);
        if (this.data._int.loaded_data.loaded_markers[lat+"|"+lon]) return 1;
        else                                return 0;
    },
    _markers_Markers_IDCollection_ReturnAll : function()   {
        return this.data._int.loaded_data.loaded_markers;
    },
    _markers_Markers_IDCollection_ClearAll : function()   {
        this.data._int.loaded_data.loaded_markers = {};
    },
    _markers_Markers_IDCollection_ClearOne : function(lat,lon)   {
        delete this.data._int.loaded_data.loaded_markers[lat+"|"+lon];
    },
    
    // Raw Markers are markers that have not yet been loaded to the map.
    _markers_RawMarkers_ReturnAll : function() {
        return this.data._int.raw_data.raw_markers;
    },
    _markers_RawMarkers_CollectOne : function()   {
        logInConsole("Adding one:");
        logInConsole(arguments[0]);
        this.data._int.raw_data.raw_markers.push(arguments[0]);
    },
    _markers_RawMarkers_HowMany : function()   {
        return this.data._int.raw_data.raw_markers.length;
    },
    _markers_RawMarkers_ClearList : function()   {
        this.data._int.raw_data.raw_markers = [];
    },
    
    
    
    
    
    
    
    
    
    
    
    /*****************************************************************************/
    /*******************       INTERNAL/PRIVATE METHODS        *******************/
    
    // **** Error Handling ****
    _err_DoNotgenerateMap_On : function()    { this.data._int.errors.doNotRenderMap = 1;    },
    _err_DoNotgenerateMap_Check : function() { return this.data._int.errors.doNotRenderMap; },
    
    
    
    
    
    // **** Setters/Getters ****
    
    //  - Map object
    object_Map : function()   {
        if (arguments.length) {
            this.data._int.objects.mapObj = arguments[0];
            this.data._int.flags.map_loaded = 1;
        };
        return this.data._int.objects.mapObj;
    },
    check_IsMapLoaded : function() {
        if (this.data._int.flags.map_loaded) return 1;
        else                                 return 0;
    },
    
    
    //  - Info Window
    myInfoWindow : function()   {
        if (arguments.length) this.data._int.objects.infoWindow = arguments[0];
        return this.data._int.objects.infoWindow;
    },
    myInfoWindow_Check : function()   {
        if (this.data._int.objects.infoWindow.length) return 1;
        else                                          return 0;
    },

    
    myInfoWindow_SetCalFunction : function()   {
        logInConsole("myInfoWindow_SetCalFunction called");
        this.myInfoWindow_CalFunction(arguments[0]);
    },
    myInfoWindow_CalFunction : function()   {
        logInConsole("myInfoWindow_CalFunction called");
        if (arguments.length) this.data._int.loaded_data.infoWindow_CallFunction = arguments[0];
        return this.data._int.loaded_data.infoWindow_CallFunction;
    },
    myInfoWindow_CalFunction_Check : function()   {
        if (this.data._int.loaded_data.infoWindow_CallFunction.length) return 1;
        else                                                           return 0;
    },
    myInfoWindow_SetTemplate : function()   {
        this.myInfoWindow_Template(arguments[0]);
    },
    myInfoWindow_Template : function()   {
        if (arguments.length) this.data._int.loaded_data.infoWindow_Template = new Template(arguments[0]);
        return this.data._int.loaded_data.infoWindow_Template;
    },
    myInfoWindow_Template_Check : function()   {
        if (this.data._int.loaded_data.infoWindow_Template.length) return 1;
        else                                                       return 0;
    },
    
    //  - Gen map Data
    _data_GenMap_Center_Lat : function()   {
        if (arguments.length) this.data.map_info.map_center_lat = arguments[0];
        return this.data.map_info.map_center_lat;
    },
    _data_GenMap_Center_Lon : function()   {
        if (arguments.length) this.data.map_info.map_center_lon = arguments[0];
        return this.data.map_info.map_center_lon;
    },
    
    _data_GenMap_Zoom : function()   {
        if (arguments.length) this.data.map_info.map_zoom = arguments[0];
        return this.data.map_info.map_zoom;
    },
    
    _data_GenMap_map_id : function()   {
        if (arguments.length) this.data.map_info.map_id = arguments[0];
        return this.data.map_info.map_id;
    },
    
    //  - Map Options
    _data_MapOpts_MapType : function()        {
        if (arguments.length) this.data.map_info.options.MapTypeId = arguments[0];
        if (!this.data.map_info.options.MapTypeId)                    return false;
        else if (this.data.map_info.options.MapTypeId == "ROADMAP")   return google.maps.MapTypeId.ROADMAP;
        else if (this.data.map_info.options.MapTypeId == "SATELLITE") return google.maps.MapTypeId.SATELLITE;
        else if (this.data.map_info.options.MapTypeId == "HYBRID")    return google.maps.MapTypeId.HYBRID;
        else if (this.data.map_info.options.MapTypeId == "TERRAIN")   return google.maps.MapTypeId.TERRAIN;
    },
    
    _data_MapOpts_MapControlType : function()        {
        if (arguments.length) this.data.map_info.options.MapTypeControlStyle = arguments[0];
        if (!this.data.map_info.options.MapTypeControlStyle)                           return false;
        else if (this.data.map_info.options.MapTypeControlStyle == "HORIZONTAL_BAR")   return google.maps.MapTypeControlStyle.HORIZONTAL_BAR;
        else if (this.data.map_info.options.MapTypeControlStyle == "DROPDOWN_MENU")    return google.maps.MapTypeControlStyle.DROPDOWN_MENU;
        else if (this.data.map_info.options.MapTypeControlStyle == "DEFAULT")          return google.maps.MapTypeControlStyle.DEFAULT;
    },
    
    _data_MapOpts_NavCtrl : function()        {
        if (arguments.length) this.data.map_info.options.navigationControl = arguments[0];
        if (!this.data.map_info.options.navigationControl)                   return false;
        else if (this.data.map_info.options.navigationControl == "SMALL")    return google.maps.NavigationControlStyle.SMALL;
        else if (this.data.map_info.options.navigationControl == "ZOOM_PAN") return google.maps.NavigationControlStyle.ZOOM_PAN;
        else if (this.data.map_info.options.navigationControl == "ANDROID")  return google.maps.NavigationControlStyle.ANDROID;
        else if (this.data.map_info.options.navigationControl == "DEFAULT")  return google.maps.NavigationControlStyle.DEFAULT;
    },
    
    
    //  - Traffic Overlay
    _objects_MapOpts_TrafficLayerObj : function()   {
        if (arguments.length) this.data._int.objects.TrafficLayer = arguments[0];
        return this.data._int.objects.TrafficLayer;
    },
    _objects_Create_TrafficLayerObj : function()   {
        this._objects_MapOpts_TrafficLayerObj(new google.maps.TrafficLayer());
        this.data._int.flags.TrafficLayervisible = false;
    },
    
    _objects_TurnOff_TrafficLayer : function()   {
        this._objects_MapOpts_TrafficLayerObj().setMap(null);
        this._data_MapOpts_Flag_AddTrafficLayer(false);
    },
    _objects_TurnOn_TrafficLayer : function()   {
        this._objects_MapOpts_TrafficLayerObj().setMap(this.object_Map());
        this._data_MapOpts_Flag_AddTrafficLayer(true);
    },
    
    _data_MapOpts_Flag_AddTrafficLayerOnLoad : function()   {
        if (arguments.length) this.data.map_info.options.addTrafficLayerOnLoad = arguments[0];
        return this.data.map_info.options.addTrafficLayerOnLoad;
    },
    _data_MapOpts_Flag_AddTrafficLayer : function()   {
        if (arguments.length) this.data._int.flags.TrafficLayervisible = arguments[0];
        return this.data._int.flags.TrafficLayervisible;
    },
    
    
    //  - Bike Overlay
    _objects_MapOpts_BicyclingLayerObj : function()   {
        if (arguments.length) this.data._int.objects.BicyclingLayer = arguments[0];
        return this.data._int.objects.BicyclingLayer;
    },
    _objects_Create_BicyclingLayerObj : function()   {
        this._objects_MapOpts_BicyclingLayerObj(new google.maps.BicyclingLayer());
        this.data._int.flags.BicyclingLayervisible = false;
    },
    
    _objects_TurnOff_BicyclingLayer : function()   {
        this._objects_MapOpts_BicyclingLayerObj().setMap(null);
        this._data_MapOpts_Flag_AddBicyclingLayer(false);
    },
    _objects_TurnOn_BicyclingLayer : function()   {
        this._objects_MapOpts_BicyclingLayerObj().setMap(this.object_Map());
        this._data_MapOpts_Flag_AddBicyclingLayer(true);
    },
    
    _data_MapOpts_Flag_AddBicyclingLayerOnLoad : function()   {
        if (arguments.length) this.data.map_info.options.addBicyclingLayerOnLoad = arguments[0];
        return this.data.map_info.options.addBicyclingLayerOnLoad;
    },
    _data_MapOpts_Flag_AddBicyclingLayer : function()   {
        if (arguments.length) this.data._int.flags.BicyclingLayervisible = arguments[0];
        return this.data._int.flags.BicyclingLayervisible;
    },
    
    
    
    fake : function() {}
    
    
});
















///////////////////////////
// Additional Functions

// Event Handling: Map Panning: This will be used to handle different
//  scenerios when the map pans.
//  additionalInformation = {
//     defaultFunction : 1,
//     load_Markers    : { see_below }
// }
function map_Pan_Drag_End_Interaction(mapObj,additionalInformation) {
    logInConsole("map_Pan_Drag_End_Interaction called");
    //logInConsole(additionalInformation);
    
    
    // Dynamically load markers when called
    if (additionalInformation.load_Markers) {
        
        interact_With_MapPoint_BackEnd(mapObj,additionalInformation);
        
    }
    
}


// Event Handling: Map Zoom: This will be used to handle different
//  scenerios when the map zooms.
//  additionalInformation = {
//     defaultFunction : 1,
//     load_Markers    : { see_below }
// }
function map_Zoom_End_Interaction(mapObj,additionalInformation) {
    logInConsole("map_Zoom_End_Interaction called");
    //logInConsole(additionalInformation);
    
    // Dynamically load markers when called
    if (additionalInformation.load_Markers) {
        
        interact_With_MapPoint_BackEnd(mapObj,additionalInformation);
        
    }
    
}







// This will request markers from the mapPoints DB and load the onto the map.
// interact_With_MapPoint_BackEnd(mapObj,{
//     load_Markers_Data : {
//         url         : 'http://mylinuxdevelopmentinstal.com/projectbill/Bill-Development-Area-V2/v2.0.6-Dev-GetOut-V3/cgi-bin/mainu.cgi?WS=call&ws_id=map-overlays',
//         markOptions : {
//             animateMarkers : 1|0
//             holdOrigData   : 1|0 // When true, we'll add the marker data sent within the marker array element for later use
//         },
//         limitations : {
//             currentBounds : 1,
//             skip_uid      : 256,
//             only_uid      : 256,
//             do_not_hide_any_overlays : 1|0,
//             make_all_draggable : 1|0,
//             currentZoom   : 1,
//             point_level   : 1 // Point Level/priority: 1 major, 2 minor
//         }
//     }
//     }});
function interact_With_MapPoint_BackEnd(mapObj,additionalInformation) {
    logInConsole("interact_With_MapPoint_BackEnd called");
    //logInConsole(mapObj);
    //logInConsole(additionalInformation);
    //logInConsole(mapObj.object_Map().getBounds());
    
    var limitations = {};
    if (additionalInformation.load_Markers) {
        limitations.load_markers_return_to_map = 1;
        if (additionalInformation.load_Markers.limitations.currentBounds) {
            limitations.return_within_bounds = mapObj.map_GetBounds();
        }
        
        if (additionalInformation.load_Markers.markOptions) {
            if (additionalInformation.load_Markers.markOptions.animateMarkers) {
                limitations.animate_markers_when_adding_to_map = 1;
            }
            if (additionalInformation.load_Markers.markOptions.holdOrigData) {
                limitations.flag_holdOrigData = 1;
            }
        }
        
        if (additionalInformation.load_Markers.limitations.point_level) {
            limitations.return_only_this_point_level = 
                additionalInformation.load_Markers.limitations.point_level;
        }
        
        if (additionalInformation.load_Markers.limitations.do_not_hide_any_overlays) {
            limitations.do_not_hide_any_overlays = 1;
        }
        
        if (additionalInformation.load_Markers.limitations.all_markers_draggable) {
            limitations.all_markers_draggable = 1;
        }
        
        if (additionalInformation.load_Markers.limitations.only_uid) {
            limitations.return_only_this_listing_uid = 
                additionalInformation.load_Markers.limitations.only_uid;
        }
        
        if (additionalInformation.load_Markers.limitations.skip_uid) {
            limitations.skip_this_listing_uid = 
                additionalInformation.load_Markers.limitations.skip_uid;
        }
    }
    
    new Ajax.Request(
        additionalInformation.load_Markers.url,
        {
            evalJS: true, // <----- notice evalJS not evalScripts
            method: 'get',
            parameters: limitations,
            onComplete: function(transport){
                
                var returnJSON = transport.responseText.evalJSON();
                //$('quicknotes_bottom').innerHTML = returnJSON;
                //logInConsole(returnJSON);
                //logInConsole(returnJSON.load_markers_return_to_map);
                //logInConsole(returnJSON.raw_markers);
                
                // load returned markers if load_markers_return_to_map is returned
                if (returnJSON.load_markers_return_to_map) {
                    logInConsole("******************************");
                    logInConsole("Will load markers soon!");
                    
                    
                    //for (i=0; i<returnJSON.raw_markers.length;i++) {
                    //    logInConsole(returnJSON.raw_markers[i]);
                    //    mapObj.markers_AddOne(returnJSON.raw_markers);
                    //}
                    mapObj.markers_AddGroup(returnJSON.raw_markers);
                    
                    
                    logInConsole("Markers ADDED!");
                    logInConsole("******************************");
                }
                
                
                }
            });
    
}



function updateFormFiendsWithLatLonZoom(map,marker,additionalData) {
    logInConsole("updateFormFiendsWithLatLonZoom called");
    logInConsole("Map Zoom: "+map.getZoom());
    logInConsole("Marker Title: "+marker.getTitle());
    logInConsole("Marker Position: "+marker.getPosition());
    if (additionalData.UpdateWhenBooleanTrue) logInConsole("additionalData.UpdateWhenBooleanTrue: "+additionalData.UpdateWhenBooleanTrue);
    
    if (additionalData.form_field_id_lat) {
        $(additionalData.form_field_id_lat).value=marker.getPosition().lat();
    }
    if (additionalData.form_field_id_lon) {
        $(additionalData.form_field_id_lon).value=marker.getPosition().lng();
    }
    if (additionalData.form_field_id_zoom) {
        $(additionalData.form_field_id_zoom).value=map.getZoom();
    }
}





function event_ZoomChange() {
    logInConsole("event_ZoomChange called");
    //logInConsole("----------------");
    //logInConsole("arguments[0]");
    //logInConsole(arguments[0]);
    logInConsole("---------------------------- 3");
    logInConsole("arguments[1]");
    logInConsole(arguments[1]);
}


function codeAddress() {
    var address = document.getElementById("address").value;
    geocoder.geocode( { 'address': address }, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
        map.setCenter(results[0].geometry.location);
        var marker = new google.maps.Marker({
            map: map, 
            position: results[0].geometry.location
        });
    } else {
        alert("Geocode was not successful for the following reason: " + status);
    }
    });
}










/*

// Misc Events
google.maps.event.addListener(map, 'dragend',function() { actualizaUbicacion() });
google.maps.event.addListener(map, 'zoom_changed',function() { actualizaUbicacion() });



Closers/Binding

Example foudn on:
    http://stackoverflow.com/questions/829353/google-maps-trouble-closures-passing-by-reference

google.maps.event.addListener(this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers], 'click', (function(map,fullMarker,markerData) { return function() {
    myInfoWindow.setContent(markerData.infoWindow_content);
    myInfoWindow.open(map, marker);
}})(this.object_Map(),this._markers_Markers_Objects_GetAll()[this.data._int.counters.markers],markerData));



*/
