var activeLocation;
var selectedArea;
var previousSpot;
var previousZoom;
var previousType;

var allMarkers = new Object();
allMarkers.thumbs = new Array();
allMarkers.response = LoadGeo();
allMarkers.responseCount = allMarkers.response.length;
        
window.setTimeout("BuildMarkers()", 400);

var allIcons = new Object();
var map;
var IsMapFiltered = false;

function setMapSize() 
{ 
    var NS = getWindowSize(); 
    
    var height = NS.width / 1.77;
    document.getElementById("map").style.height = height + 'px'; 
    
    // (NS.height - 130)
} 

function getWindowSize() 
{ 
    var e = new Object(); 
    if(window.self && self.innerWidth) 
    { 
        e.width = self.innerWidth; 
        e.height = self.innerHeight; 
    } 
    else if(document.documentElement && document.documentElement.clientHeight) 
    { 
        e.width = document.documentElement.clientWidth; 
        e.height = document.documentElement.clientHeight; 
    }
    else 
    { 
        e.width = document.body.clientWidth; 
        e.height = document.body.clientHeight; 
    } 
    return e;
} 
 

var activeLocIcon = new GIcon();
activeLocIcon.image = "http://www.google.com/mapfiles/gadget/arrowSmall80.png";
activeLocIcon.shadow = "http://www.google.com/mapfiles/gadget/arrowshadowSmall80.png";;
activeLocIcon.iconSize = new GSize(31, 27);
activeLocIcon.shadowSize = new GSize(31, 27);
activeLocIcon.iconAnchor = new GPoint(8, 27);
activeLocIconinfoWindowAnchor = new GPoint(5, 1); 

function GetLocationInfo_Callback(response)
{
    if(response.error != null)
    {
        var errorx = "Error: ";
        for(var i in response.error)
        {
            errorx += "Name: " + i + "   Value: " + response.error[i] + "\r\n";
        }
        alert(errorx);
    }
    
    if(response.value != null)
    {
        document.getElementById('InfoWindowLocationInfo').innerHTML = response.value;
    }
}

// Generates an infoWindow from values attached to the marker   
function displayMarker(overlay)
{
    var marker = allMarkers[overlay.MIndex];
    
    if(overlay.isHidden) overlay.show();
    
    var loc = overlay.getPoint();
    
    // Recenter the map on this location
	//map.setCenter(loc); 
    RootPage.GetLocationInfo(marker.ID, GetLocationInfo_Callback);
	
	// Prepare the infowindow HTML   
    var html = "<div style='width: 400px;'><strong>" + marker.Title + "</strong>";
    if(marker.Thumb != "")
    {
        html += "";
    }           
    html +=     "<div style='margin: 3px; color: #696969;'>" +
                "<div style='font-weight: normal; height: 140px; overflow: auto;' id='InfoWindowLocationInfo'>" +
                "<img src='/images/indicator.gif' title='loading...' style='margin: 10px;' />" + 
                "<\/div><div style='padding-top: 2px;'><a href='Info.aspx?Location=" + 
                marker.ID + 
                "'>More Info &raquo; <\/a><img class='pointerhand' src='/images/zoom.png' onclick='AtlasZoom(" + 
                loc.lat() + "," + loc.lng() + ",this);' /><\/div><\/div>";
    
    
    
    // Display the infowindow
    overlay.openInfoWindowHtml(html);
}

// Handle when a user clicks the map    
function map_click(overlay, point) 
{
    if(activeLocation != null)
	    map.removeOverlay(activeLocation);
    
    if (overlay) 
	{
	    // Infowindow's are overlays (and others), exit if an overlay was
	    // clicked but doesn't have our assigned MIndex property
	    if(overlay.MIndex == null) return
    
        displayMarker(overlay)
        point = overlay.getPoint();
	    
	}
	else
	{
	    if(!point) return;
	    
        activeLocation = new GMarker(point, activeLocIcon);
        map.addOverlay(activeLocation);
    }
    
	RootPage.DisplayLocationDetails(point.y,  point.x, map.getZoom(), DisplayLocationDetails_Callback);
}

// Similar effect as when a user clicks on a the map at a given location
// Takes a lat/lng paramenter set and adds an 
function SetActiveLocation(lat, lng)
{
    if(activeLocation != null)
        map.removeOverlay(activeLocation);
    
    var latlng = new GLatLng(lat, lng);
    activeLocation = new GMarker(latlng, activeLocIcon);
    map.addOverlay(activeLocation);
    
    map.setCenter(latlng);
    
	RootPage.DisplayLocationDetails(latlng.y,  latlng.x, map.getZoom(), DisplayLocationDetails_Callback);
}

// Set-up to use getMouseXY function onMouseMove
//document.onclick = getMouseXY;


document.getElementById('map').onmousemove = getMouseXY;

// Temporary variables to hold mouse x-y pos.s
var tempX = 0
var tempY = 0

// Main function to retrieve mouse x-y pos.s
function getMouseXY(e) {
  if (e == null) { // grab the x-y pos.s if browser is IE
    tempX = event.clientX + document.body.scrollLeft
    tempY = event.clientY + document.body.scrollTop
  } else {  // grab the x-y pos.s if browser is NS
    tempX = e.pageX
    tempY = e.pageY
  }  
  // catch possible negative values in NS4
  if (tempX < 0){tempX = 0}
  if (tempY < 0){tempY = 0}  

  return true
}

function DisplayLocationDetails_Callback(response)
{

    if(response.error != null)
    {
        var errorx = "Error: ";
        for(var i in response.error)
        {
            errorx += "Name: " + i + "   Value: " + response.error[i] + "\r\n";
        }
        alert(errorx);
    }
    
    if(response.value != null)
    {
        document.getElementById("nearby").innerHTML = response.value.Html;
        
        /*
        var r = response.value.RangeInfo;
        
        var pLine = new GPolyline([
            new GLatLng(r.LatStart, r.LngStart), 
            new GLatLng(r.LatEnd, r.LngStart), 
            new GLatLng(r.LatEnd, r.LngEnd), 
            new GLatLng(r.LatStart, r.LngEnd),
            new GLatLng(r.LatStart, r.LngStart)], "#ff0000", 2);
	  

	    if(selectedArea)
	        map.removeOverlay(selectedArea);
	    
	    map.addOverlay(pLine);
	    
	    selectedArea = pLine;
	    */
    }
}

// Supports the 'Zoom In' feature displayed on each markers InfoWindow
function AtlasZoom(lat, lng, img)
{
    if(img.src.indexOf('zoom.png') != -1)
    {
        // Store the current zoom and position of the map
        previousSpot = map.getCenter();
        previousZoom = map.getZoom();
        previousType = map.getCurrentMapType();
        
        // Zoom in and set the map to aerial view
        map.setCenter(new GLatLng(lat, lng), 12, G_NORMAL_MAP);

        // Update image to reflect modified state
        img.src = '/images/restore.png'
    }
    else
    {
        // Restore the map zoom and position
        map.setCenter(previousSpot, previousZoom, previousType);
        
        // Update image to reflect modified state
        img.src = '/images/zoom.png';
    }                
}

// Loads locations from the database onto the map 
function GetGeoLocations_Callback(response)
{
    if(response.error)
    {
        var errorx = "Error: ";
        for(var i in response.error)
        {
            errorx += "Name: " + i + "   Value: " + response.error[i] + "\r\n";
        }
        alert(errorx);
    }
    
    if(response.value != null)
    {
        //var icon = GetDefaultMarkerIcon();

        // Assign the allMarkers object the json array of markers from
        // the ajax call result
        allMarkers = new Object();
        allMarkers.thumbs = new Array();
        allMarkers.response = response.value;
        allMarkers.responseCount = response.value.length;
        
        window.setTimeout("BuildMarkers()", 200);
        
        return; 
        
        // Loop over the objects, create a google marker for each and add it to the map
        for(i = 0; i < response.value.length; i++)
        {
            var marker = response.value[i];
            
            // Create a new property/hash entry for our marker
            allMarkers[marker.ID] = marker;
            
            if(marker.Thumb != 0)
            {
                allMarkers.thumbs.push(marker.ID);
            }
            
            // At some point the marker's icon should be tested and different
            // ones selected for the GMarker parameter
            marker.GMarker = new GMarker(new GPoint(marker.Lng, marker.Lat), allIcons[marker.Ico]);
            
            GEvent.addListener(marker.GMarker, 'mouseover', mouseOverMarker);
            GEvent.addListener(marker.GMarker, 'mouseout', mouseOverOut);
            
            // Give the new overlay a key that can then be used to reference
            // the parent object in allMarkers when events fired from the map
            // don't give us enough context to figure it out otherwise
            marker.GMarker.MIndex = marker.ID;
            map.addOverlay(marker.GMarker);
        }
        ChangeSource();
    }
}

function IsTopLevelMarker(marker,b) 
{
    return allMarkers[marker.MIndex].Ico;
}

function BuildMarkers()
{
    // If somehow the map hasn't yet initialized but we have markers... queue until the desired map state is entered
    if(!map.isLoaded()) window.setTimeout("BuildMarkers()", 100);
    
    // Do n iterations before yeilding control for n milliseconds
    for(var i = 0; i < 25; i ++)
    {
        // Loop over the objects, create a google marker for each and add it to the map
        var marker = allMarkers.response.pop(); 
        
        if(marker != null)
        {
            // Create a new property/hash entry for our marker
            allMarkers[marker.ID] = marker;
            
            if(marker.Thumb != 0)
            {
                allMarkers.thumbs.push(marker.ID);
            }
            
            marker.GMarker = new GMarker(new GPoint(marker.Lng, marker.Lat),{icon: allIcons[marker.Ico], zIndexProcess: IsTopLevelMarker});
            
            //GEvent.addListener(marker.GMarker, 'mouseover', mouseOverMarker);
            //GEvent.addListener(marker.GMarker, 'mouseout', mouseOverOut);
            
            // Give the new overlay a key that can then be used to reference
            // the parent object in allMarkers when events fired from the map
            // don't give us enough context to figure it out otherwise
            marker.GMarker.MIndex = marker.ID;
            map.addOverlay(marker.GMarker);
        }
        else
        
        {
            // Markers are fully imported, fire ChangeSource and do not queue another call for this function
            document.getElementById('LoadingBox').style.display = 'none';
            document.getElementById('accordion').style.display = 'block';
            document.getElementById('SlideShow').style.display = 'block';

            // This line was causing an error in Safari windows and it seemed to be timing based
            // where the onclick function wasn't yet assigned - the WaitForMenu.. function
            // works around this issue
            //document.getElementById('fxVirtual').getElementsByTagName('a')[0].onclick();
            WaitForMenuAndExpand();
            
            // Start the thumbnail rotation/slideshow
            ChangeSource();
            
            // Exit the function at this point to prevent further calling from the setTimeout below
            return;
        }
    }
    document.getElementById('LoadingBox').getElementsByTagName('h5')[0].innerHTML = 'Loading ' + (allMarkers.responseCount - allMarkers.response.length) + ' of ' +  allMarkers.responseCount; 
    window.setTimeout("BuildMarkers()", 20);
}

function WaitForMenuAndExpand()
{
    // Trying to call the onclick function before the element has it's display: none property reset
    // causes the action to fail and thus not get expanded
    if(document.getElementById("accordion").style.display == '')
    {
        setTimeout("WaitForMenuAndExpand()", 300);
    }
    else
    {
        // When they're all setup, display/expand the menu item in the accordion
        document.getElementById('fxVirtual').getElementsByTagName('a')[0].onclick();
    }
}

function mouseOverOut()
{
    var elem = document.getElementById('imgHover');
    elem.style.display = 'none';    
}

function mouseOverMarker()
{
    // Exit if a server side thumbnail wasn't found
    if(allMarkers[this.MIndex].Thumb == 0) return;
    
    //document.getElementById("SlideShowImage").src = "/images/thumbs/" + this.MIndex + "_t.png";
    
    var elem = document.getElementById('imgHover');
    var leftOffset = document.getElementById('map').offsetLeft;
    var topOffset = document.getElementById('map').offsetTop;
    
    if(elem  == null)
    {
        elem = document.createElement("img");
        elem.id = 'imgHover';
        //elem.attributes['style'] = 'position: absolute; z-index: 1000;'
        elem.style.position = 'absolute';
        elem.style.height = '90px';
        elem.style.width = '120px';
        elem.style.zIndex = '1000';
        elem.style.border = 'solid 1px #e9e9e9';
        document.getElementById('map').appendChild(elem);
    }
    
    //var mx = map.fromLatLngToDivPixel(this.getPoint())
    
    elem.src = "/images/thumbs/" + this.MIndex + "_t.png";
    elem.style.left = tempX - leftOffset -  60 + 'px';
    elem.style.top = tempY - topOffset - 115 + 'px';
    elem.style.display = '';    
}

// Called the "Nearby" links to display an infoWindow for the selected location
function selectMarkerByID(locationID)
{
    document.getElementById('map').scrollIntoView();
    
    // Display it when found
    displayMarker(allMarkers[locationID].GMarker);
}

window.onresize = setMapSize;
setMapSize();

map = new GMap2(document.getElementById("map"));
//map.addControl(new GOverviewMapControl()); //GSmallMapControl()
//map.addControl(new GMapTypeControl());

var customUI = map.getDefaultUI();
customUI.controls.largemapcontrol3d = false;

map.setUI(customUI);
map.addControl(new GLargeMapControl3D(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10, 40))); //GSmallMapControl()


GEvent.addListener(map, 'click', map_click);
GEvent.addListener(map, 'load', map_Loaded);

map.setCenter(new GLatLng(47.07012182383309, -120.6683349609375) , 8);
map.setMapType(G_PHYSICAL_MAP); 

allIcons[0] = LoadMiniIcon('yellow.png');
allIcons[1] = LoadMiniIcon('blue.png');

var geocoder = new GClientGeocoder();

document.getElementById('LoadingBox').getElementsByTagName('h5')[0].innerHTML = 'Requesting Markers...';

// Call function to load locations
//RootPage.GetGeoLocations(GetGeoLocations_Callback);

function LoadMiniIcon(colorImage)
{
   var icon = new GIcon();

    // Create our "tiny" marker icon
    icon.image = "/images/markers/" + colorImage;
    icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(12, 20);
    icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(6, 20);
    icon.infoWindowAnchor = new GPoint(5, 1);
    
    return icon;
}
            
function DoGeoLookup()
{
    var address = document.getElementById('txtAddrSearch').value; 
    geocoder.getLatLng(address, function(point)
        {
            if (!point) {
                alert("Geocoding failed for '" + address + "'");
            } else {
                // Create a base icon for all of our markers that specifies the
                // shadow, icon dimensions, etc.
                var icon = new GIcon();
                icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
                icon.iconSize = new GSize(20, 34);
                icon.shadowSize = new GSize(37, 34);
                icon.iconAnchor = new GPoint(9, 34);
                icon.infoWindowAnchor = new GPoint(9, 2);
                icon.infoShadowAnchor = new GPoint(18, 25);
                icon.image = "/images/markers/125.png";

                var marker = new GMarker(point, icon);
                map.addOverlay(marker);
                map.setCenter(point);
                marker.openInfoWindowHtml(address);
                
                GEvent.addListener(marker, "click", function() {
                    marker.openInfoWindowHtml(address);
                });
            }
        });
}



function GetDefaultMarkerIcon()
{
    var icon = new GIcon();

    // Create our "tiny" marker icon
    icon.image = "/images/markers/yellow.png";
    icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    icon.iconSize = new GSize(12, 20);
    icon.shadowSize = new GSize(22, 20);
    icon.iconAnchor = new GPoint(6, 20);
    icon.infoWindowAnchor = new GPoint(5, 1);
    
    return icon;
}

function showOverlays()
{
    var hitlist = 'thumbs,responseCount,response';
    for (var n in allMarkers) {
        // Ignored specified members/properties
        if(hitlist.indexOf(n) != -1) continue;
        allMarkers[n].GMarker.show();
    }
}

function hideOverlays()
{
    IsMapFiltered = true;
    var hitlist = 'thumbs,responseCount,response';
    for (var n in allMarkers) {
        // Ignored specified members/properties
        if(hitlist.indexOf(n) != -1) continue;
        allMarkers[n].GMarker.hide();
    }
}

function showVirtualTour(elem, locID)
{
    UpdateActiveFilterElem(elem);
    
    // Select the marker on the map
    selectMarkerByID(locID);
    
    // Setup to be notified when it's closed (and thus reset the ActiveFilterElem stuff)
    GEvent.addListener(map.getInfoWindow(), 'closeclick', updateBarOnInfoWindowClose);
    
}

function updateBarOnInfoWindowClose()
{
    if(activeFilterElem)
    {
        activeFilterElem.className = '';
    }
}

var activeFilterElem = null;

// Update the clicked element to show that it's the active filter
function UpdateActiveFilterElem(elem)
{
    // Reset the previous item
    if(activeFilterElem)
    {
        activeFilterElem.className = '';
    }
    
    // Update the new one
    elem.className = 'active'; 
    
    // Save the new one to reset later
    activeFilterElem = elem;
}

// Abstract function which preps a change from one filter to the next
function BeginFilter(elem)
{
    UpdateActiveFilterElem(elem);
   
    // Hide all markers
    hideOverlays();

    // Maker sure the map is visible
    $('infoClickMap').scrollIntoView();
    
    // Close any open infowindows
    map.closeInfoWindow();
    
}

function filterRegion(anchor)
{
    BeginFilter(anchor);

    var isDisplayed = false;
    var firstItem = null;
    var localList = BuildKeyedFromCSV(regionList[anchor.getAttribute('title')]);

    for (var n in allMarkers)
    {
        var winery = allMarkers[n];
        if(localList[winery.ID] == 1)
        {
            winery.GMarker.show();
            
            if(!isDisplayed)
            {
                firstItem = winery.GMarker;
                isDisplayed = true;
            }
        }
    }
    
    if(firstItem != null)
    {
        map.panTo(firstItem.getPoint());
    }

}

// Build a keyed aka Hash type object for quick lookup of members from a CSV string. 
// I feel like there's a simple solution right at my finger tips where I search the string 
// directly but it's not occuring to me how to search for 101 and not match 1012...
function BuildKeyedFromCSV(csv)
{
    var split = csv.split(',');
    var obj = new Object();
    for(var i = 0; i < split.length; i++)
    {
        obj[split[i]] = 1;
    }
    
    return obj
}

function filterCity(anchor)
{
    BeginFilter(anchor);
    
    var isDisplayed = false;
    var firstItem = null;
    var localList = BuildKeyedFromCSV(cityList[anchor.getAttribute('title')]);

    for (var n in allMarkers)
    {
        var winery = allMarkers[n];
        if(localList[winery.ID] == 1)
        {
            winery.GMarker.show();
        
            if(!isDisplayed)
            {
                firstItem = winery.GMarker;
                isDisplayed = true;
            }
        }
    }
    
    if(firstItem != null)
    {
        map.panTo(firstItem.getPoint());
    }
    

}

function filterHasMedia()
{
    showOverlays();
    return;

    hideOverlays();
   
//    var isDisplayed = false;
//    var firstItem = null;
    
    for (var n in allMarkers)
    {
        var winery = allMarkers[n];
        
        if(winery.HasMedia)
        {
            winery.GMarker.show();
        }
        
//        if(!isDisplayed)
//        {
//            firstItem = winery.GMarker;
//            isDisplayed = true;
//        }

    }
    
//    if(firstItem != null)
//    {
//        map.panTo(firstItem.getPoint());
//    }

}


function filterTag(anchor)
{
    BeginFilter(anchor);

    var tag = anchor.getAttribute('title');

    // Initiate ajax call
    RootPage.GetWinerysFromTag(tag, function(response) { 
        
        //hideOverlays();
        
        if(response.error)
        {
            var errorx = "Error: ";
            for(var i in response.error)
            {
                errorx += "Name: " + i + "   Value: " + response.error[i] + "\r\n";
            }
            alert(errorx);
        }
    
        if(response.value != null)
        {
        
//            var isDisplayed = false;
//            var firstItem = null;

            // Assign the allMarkers object the json array of markers from
            // the ajax call result
            var tags = response.value;
            
            // Loop over every defined marker
            for (var n in allMarkers)
            {
                // Check to see if the marker was matched by the tag
                for(var j = 0; j < tags.length; j++)
                {
                    // Display the marker if so and exit the inner for loop
                    if(tags[j] == n)
                    {
                        allMarkers[n].GMarker.show();
                    
//                        if(!isDisplayed)
//                        {
//                            firstItem = allMarkers[n].GMarker;
//                            isDisplayed = true;
//                        }
                        
                        // Exit the internal loop on match
                        break;
                    }
                }
            }
//            
//            if(firstItem != null)
//            {
//                map.panTo(firstItem.getPoint());
//            }

        }
    });
}

function map_Loaded()
{
    //var kml = new GGeoXml("http://www.teampain.com/flash/news/Updated%203-22-07.kmz");
    //map.addOverlay(kml);
}

