	//EDITORS - configure error messages //
	sameLocationMessage = "You are already there.";
	tooGeneralMessage = "Can you be more specific ('science center' instead of 'science')? Or include an address, city, and state.";
	cantFindMessage = "I can't find that location.";
	//END Error messages//
	//DEFAULT INFO WINDOW TEXT//
	johnstonMessage = "Johnston Gate<br/>If living in Yard or Union dorms, enter through this gate to pick up your key and move in.";
	//END EDITORIAL BLOCK
var fromLat = null;
var fromLng = null;
var map = "";
var destMarker = "";
var startMarker = "";
var directionsDisplay;
var directionsService;
var hsMap;
var myOptions;
var directionMode = "DRIVING";
var contentString;
var mapListObject;
var geocoder;
var completeList;
var destination = false;
var reject = false;
var infowindow = new google.maps.InfoWindow({
    content: ""
});
var whichBuilding = "";
var geoResult;
hs.Expander.prototype.onAfterExpand = function(){getMapHS(whichBuilding);};

function showDirections() {
    $(".toggleDirections").hide();
    $(".directionControl").show();
}

function isArray(obj) {
   if (obj.constructor.toString().indexOf("Array") == -1)
      return false;
   else
      return true;
}

//There is some debate of the value of clearing the from box onclick/focus - this is where it happens


function setupFromBox(from) {
    $(from).click(function() {
        fromLat = null;
        fromLng = null;
        $(from).val("");
    });
    $(from).focus(function() {
        fromLat = null;
        fromLng = null;
        $(from).val("");
    });
    $.getJSON("/incl/data/harvard_buildings.json", function(data) {
        completeList = data.items;
        $(from).autocomplete({
            source: completeList,
            minLength: 3,
            focus: function(event, ui) {
                $(from).val(ui.item.value);
                fromLat = null;
                fromLng = null;
                return false;
            },
            select: function(event, ui) {
                fromLat = ui.item.lat;
                fromLng = ui.item.lon;
            }
        });
    });

}

//Create dropdowns based on map.json, which is stored in mapListObject


function buildSelect() {
    var tag = $('#tagSelect').val();
    $("#mapSelect").html("<option value='all'>--Building name--</option>");
    $.each(mapListObject, function(i, item) {
        if (item.tags.indexOf(tag) !== -1 || tag === "all") {
            $("#mapSelect").append("<option value='" + item.coord + " 'title='" + item.desc + "'>" + item.title + "</option>");
        }
    });
}

function setupMap() {
    geocoder = new google.maps.Geocoder();
    directionsService = new google.maps.DirectionsService();
    mapfile = "/incl/data/map.json";
    if (destination) {
        mapfile = "data/map.json";
    }

    $.getJSON(mapfile, function(json) {
        mapListObject = json;
        $("#mapSelect").html("<option value='all'>--Building name--</option>");
        $.each(mapListObject, function(i, item) {
            $("#mapSelect").append("<option value='" + item.coord + " 'title='" + item.desc + "'>" + item.title + "</option>");
        });
    });
    directionsDisplay = new google.maps.DirectionsRenderer();
    latlng = new google.maps.LatLng(42.37469, -71.118532);
    myOptions = {
        zoom: 16,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map($("#map_canvas")[0], myOptions);
    destMarker = new google.maps.Marker({
        position: latlng,
        map: map,
        title: "Johnston Gate"
    });
    infowindow = new google.maps.InfoWindow({
        content: "<div style='height:150px;width:150px;'>" + johnstonMessage + "</div>"
    });
    google.maps.event.addListener(destMarker, 'click', function() {
        infowindow.open(map, destMarker);
    });
    directionsDisplay.setMap(map);
    directionsDisplay.setPanel($("#route")[0]);
}

function getDirections() {
    if (($('#startLoc').val() !== '') && (($('#mapSelect').val() !== null) && ($('#mapSelect').val() !== 'all'))) {
        $("#route").html("");
        var endPoint = $.trim($('#mapSelect').val()).split(",");
        startingPoint = getCoords();
        legal = true;
        var end = new google.maps.LatLng(endPoint[0], endPoint[1]);
        if ((startingPoint.lat !== "") && (startingPoint.lng !== "")) {
            start = new google.maps.LatLng(startingPoint.lat, startingPoint.lng);
            if (start.equals(end) === true) {
                legal = false;
            }
        }
        else {
            start = $('#startLoc').val();
            legal = true;
        }
        if ((legal) && (reject === false)) {
            var request;
            switch (directionMode) {
            case 'DRIVING':
                request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };
                break;
            case 'WALKING':
                request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.WALKING
                };
                break;
            case 'BICYCLING':
                request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.BICYCLING
                };
                break;
            default:
                request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };
                break;
            }
            directionsService.route(request, function(response, status) {
                if (status === google.maps.DirectionsStatus.OK) {
                    $("#route").html("");
                    directionsDisplay.setDirections(response);
                    directionsDisplay.setMap(map);
                }

            });
        }
        else if (reject === false) {
            alert(sameLocationMessage);
            map.setCenter(new google.maps.LatLng(startingPoint.lat, startingPoint.lng), 12);
            infowindow.close();
            infowindow = new google.maps.InfoWindow({
                content: contentString
            });
            destMarker = new google.maps.Marker({
                position: new google.maps.LatLng(lat, lng),
                map: map,
                title: $('#mapSelect :selected').text()
            });

            google.maps.event.addListener(destMarker, 'click', function() {
                infowindow.open(map, destMarker);
            });
        }
    }
    else if (fromLat !== null && fromLng !== null) {
        centerMap();
    }
}

//This function looks up a string (place) first in the Harvard Map and then as a failsafe from Google's geocoder. It returns a value object which contains lat/lng and sometimes a photo url as well.


function getCoords(place) {
    reject = false;
    if (place === "" || place === undefined) {
        place = $.trim($("#startLoc").val());
    }
    var value = {
        photo: "",
        lat: "",
        lng: "",
        title: "",
        address: "",
        desc: ""
    };
    var dataOb = null;
    //Don't choke on punctuation!!
    tmp = place.replace("(", "\\(");
    tmp = tmp.replace(")", "\\)");
    tmp = tmp.replace(",", "\\,");
    placeExp = new RegExp(tmp, "i"); //Someday I might try to write a more sophisticated regex to match a little more cleanly
    var matches = $.grep(completeList, function(a) {
        return a.value.search(placeExp) !== -1;
    }); //THIS IS WHERE THE MAGIC HAPPENS - check to see if there's an official building with the specified name
    var extraMatches = jQuery.grep(matches, function(a) {
        return ((a.lon !== matches[0].lon) && (a.lat !== matches[0].lat));
    }); //find out if there are too many results
    if (extraMatches.length > 1) {
    	tmpPlace="";
    	for(i in matches){
    		if(($.trim(place)===matches[i].value)||($.trim(place)+" A"===matches[i].value)){
    			value.lat = matches[i].lat;
    			value.lng = matches[i].lon;
    			value.title = matches[i].value;
    			tmpPlace=matches[i].value;
    		}
    	}
    	if(tmpPlace===""){
        alert(tooGeneralMessage);
        reject = true;
        }
    }
    else if (matches.length > 0) {
        value.lat = matches[0].lat;
        value.lng = matches[0].lon;
        value.title = matches[0].value; //This might be wrong - if there were multiple hits at the same latlng, it will title the infowindow with the first title, not necessarily the one they searched for
    }
    fromLat = value.lat;
    fromLng = value.lng;
    return value;
}

function centerMap() {
    directionsDisplay.setMap(null);
    if (($('#mapSelect').val() !== null) && ($('#mapSelect').val() !== 'all')) {
        contentString = "<div style='height:120px;width:150px;'>" + $('#mapSelect :selected').attr('title') + "</div>";
        loc = $('#mapSelect').val();
        loc = loc.split(",");
        lat = $.trim(loc[0]);
        lng = $.trim(loc[1]);
        refreshMap(lat, lng, contentString);
    }
    else if ((($("#startLoc").val() !== null) && ($("#startLoc").val() !== "")) && ((fromLat === null) || (fromLng === null))) {
        p = getCoords();
        if ((p.lat === "") || (p.lng === "")) {
            geocoder.geocode({
                'address': $("#startLoc").val()
            }, function(results, status) {
                if ((status === google.maps.GeocoderStatus.OK) && ("geometry.location" in results[0])) {
                    lat = results[0].geometry.location.b;
                    lng = results[0].geometry.location.c;
                    refreshMap(lat, lng, contentString);
                } else {
                    alert(cantFindMessage);
                }
            });

        }
        else {
            lat = p.lat;
            lng = p.lng;
        }
    }
    else if ((fromLat !== null) && (fromLng !== null)) {
        lat = fromLat;
        lng = fromLng;
        contentString = $("#startLoc").val(); //This sets the value of the infowindow to match the user's input. I'm not sure if there's another, better option, but I kinda think there must be.
        refreshMap(lat, lng, contentString);
    }
    else {
        alert(cantFindMessage);
    }
}

function refreshMap(lat, lng, contentString) {
    map.setCenter(new google.maps.LatLng(lat, lng), 12);
    infowindow.close();
    infowindow = new google.maps.InfoWindow({
        content: contentString
    });
    destMarker.setMap(null);
    if (($("#startLoc").val() !== null) && ($("#startLoc").val() !== "") && ($('#mapSelect').val() !== null) && ($('#mapSelect').val() !== 'all')) {
        getDirections();
    }
    else {
        destMarker = new google.maps.Marker({
            position: new google.maps.LatLng(lat, lng),
            map: map,
            title: $('#mapSelect :selected').text()
        });

        google.maps.event.addListener(destMarker, 'click', function() {
            infowindow.open(map, destMarker);
        });
    }

}

function setDesktopDirectionMode(mode, id) {
    id = "#" + id;
    $(".dirButtons div").removeClass('active');
    $(id).addClass('active');
    directionMode = mode;
    getDirections();
}

//hopefully the json file will be cached, otherwise this could get pretty gross.
function setupHSMap() {
    $.getJSON("/incl/data/harvard_buildings.json", function(json) {
        completeList = json.items;
    });
    geocoder = new google.maps.Geocoder();
}

//Gets coordinates of buildingname from official list/geocode, then displays the map - DEPENDS ON /incl/popMap.jsp !!
function getMapHS(buildingName) {
    coordObj = getCoords(buildingName);
        if ((coordObj.lat === "") || (coordObj.lng === "")) {
            geocoder.geocode({
                'address': buildingName
            }, function(results, status) {
            		geoResult = results;
                if ((status === google.maps.GeocoderStatus.OK) && (isArray(results))) {
                    lat = results[0].geometry.location.lat();
                    lng = results[0].geometry.location.lng();
                    showMapHS(lat,lng);
                    hsMap.setCenter(results[0].geometry.location);
                } 
                else if (status === google.maps.GeocoderStatus.OK){
                	lat = results.geometry.location.lat();
                    lng = results.geometry.location.lng();
                    showMapHS(lat,lng);
                    hsMap.setCenter(results.geometry.location);
                }
                else {
                    alert(cantFindMessage);
                }
            });

        }
        else {
            lat = coordObj.lat;
            lng = coordObj.lng;
            showMapHS(lat,lng);
        }
    
        //title: item.title
    }

function showMapHS(lat, lng){
hsMap = null;
    destMarker = null;
    latlng = new google.maps.LatLng(lat, lng);
    myOptions = {
        zoom: 16,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    hsMap = new google.maps.Map($("#map_canvas_hs")[0], myOptions);
    destMarker = new google.maps.Marker({
        position: latlng,
        map: hsMap
});
}	


