// Create our "tiny" marker icon
var icon = new GIcon();
icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.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);

var state = new PageState();

function createRequestObject() {
    var req = false;
    if(window.XMLHttpRequest) {
        try {
                        req = new XMLHttpRequest();
        } catch(e) {
                        req = false;
        }
    // branch for IE/Windows ActiveX version
    } else if(window.ActiveXObject) {
        try {
                req = new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
            try {
                        req = new ActiveXObject("Microsoft.XMLHTTP");
                } catch(e) {
                        req = false;
                }
            }
    }
    return req;
    
}

// handles the javascript literal points returned from the MBTA munger
function processReqChange() {
    if ((req.readyState == 4) && (req.status == 200)) {
        js = req.responseText;
        
        eval(js);
        displayPoints();
    }
}

// request the stops (and associated times) near the specified lat/lon
function updatePoints(lat, lon) {
    req = createRequestObject();
//    alert("lat= " + lat + " lon= " + lon);
    req.open("GET", "mbtanearby.py?lat=" + lat + "&lon=" + lon, true);
    req.onreadystatechange = processReqChange;
    req.send(null);
}


function geocode(addr) {
    geoReq = createRequestObject();
    geoReq.open("GET", "geocoderproxy.py?loc=" + addr, true);
    geoReq.onreadystatechange = processGeocodeResult;
    startWaiting();
    geoReq.send(null);
}

function processGeocodeResult() {
    if ((geoReq.readyState == 4) && (geoReq.status == 200)) {
        result = geoReq.responseText;
        eval(result);
        if (!codedAddr.error) {
            newLoc = new GPoint(codedAddr.lon, codedAddr.lat);
            stopWaiting();
            clearGeocodingError();
            setCurrentAddress(codedAddr.addr);
            setLocation(newLoc);
        } else {
            stopWaiting();
            raiseGeocodingError();
        }
    }
}

function clearGeocodingError() {
    addr = document.getElementById("curr_addr");
    addr.style.color = "black";
    addr.style.textDecoration = "none";
}

function raiseGeocodingError() {
    addr = document.getElementById("curr_addr");
    addr.style.color = "red";
    addr.style.textDecoration = "line-through";
    state.addr = "";
    state.save();
}

function setAddressDefault() {
    addr = document.getElementById("curr_addr");
    addr.style.color = "#c0c0c0";
    addr.style.textDecoration = "none";
    addr.innerHTML = "Click here to enter an address";
    state.addr = "";
    state.save();
}

function addressKeypress(evt) {
    var event = evt || window.event;
    var keyCode = event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode);
    if (keyCode == 13) {
        submitAddressInput();
    }
}

function submitAddressInput() {
    input = document.getElementById("addr_input").value;
    setCurrentAddress(input);
    if (input.length > 0) {
        geocode(input);
    } else {
        setAddressDefault();
    }
    endAddressEdit();
}

function setCurrentAddress(addrText) {
    document.getElementById("curr_addr").innerHTML = addrText;
    state.addr = addrText;
    state.save();  
}

function startAddressEdit() {
    var disp = document.getElementById("address_disp");
    var edit = document.getElementById("address_edit");
    disp.style.display = "none";
    edit.style.display = "block";
    var addrField = document.getElementById("addr_input");
    addrField.focus();
}

function endAddressEdit() {
    var disp = document.getElementById("address_disp");
    var edit = document.getElementById("address_edit");
    disp.style.display = "block";
    edit.style.display = "none";
}

function startWaiting() {
    var addrField = document.getElementById("addr_input");
    var addrVal = addrField.value;
    addrField.disabled = true;
    addrField.value = '';
    addrField.value = addrVal;
    document.getElementById("find_addr").disabled = true;      
}

function stopWaiting() {
    document.getElementById("addr_input").disabled = false;
    document.getElementById("find_addr").disabled = false;      
}

// processes the stop & time info into the desired HTML format for display in the popup balloons
function getStopHTML(point) {
    var htmlArr = new Array();
    htmlArr.push("<div class='stoppop'><span class='stop'>");
    htmlArr.push(point.name);
    htmlArr.push("</span><br>");
    var routesArr = new Array();
    var routes = point.times;
    for (var i = 0; i < routes.length; i++) {
        var route = routes[i];
        routesArr.push("<span class='routenum'>");
        routesArr.push(route.number);
        routesArr.push("</span>");
        routesArr.push(" ");
        routesArr.push("<span class='routename'>");
        routesArr.push(route.name);
        routesArr.push("</span>");
        routesArr.push("<br/>");
        times = route.times;
        var timesArr = new Array();
        var numtimes = Math.min(3, times.length);
        for (var j = 0; j < numtimes; j++) {
            var vehtime = times[j];
            vehtime = vehtime.replace(/^0/, '');
            timesArr.push(vehtime);
        }
        routesArr.push(timesArr.join(', '));
        routesArr.push("<br/>");
    }
    htmlArr.push(routesArr.join(''));
    htmlArr.push("</div>");
    return htmlArr.join('');
}

// create a marker for a given transit point
function createMarker(point) {
    var marker = new GMarker(new GPoint(point.lon, point.lat));
    var html = getStopHTML(point);
    marker.stop = point.name;
    marker.click = function() {
        marker.openInfoWindowHtml(html);
    };
    GEvent.addListener(marker, "click", function() {
        marker.click();
    });
    GEvent.addListener(marker, "infowindowopen", function() {
        state.stop = marker.stop;
        state.save();
    });
    GEvent.addListener(marker, "infowindowclose", function() {
        state.clearStop();
        state.save();
    })
    return marker;
}

// create a marker to represent the current base location
function createMeMarker(lat, lon) {
    var marker = new GMarker(new GPoint(lon, lat), icon);
    var html = "You Are Here<br/>(computing nearest stops from this point)";
    GEvent.addListener(marker, "click", function() {
        marker.openInfoWindowHtml(html);
    });
    return marker;
}

// process the points returned from the MBTA server query
function displayPoints() {
    var activeMarker;
    for (var i = 0; i < points.length; i++) {
        var point = points[i];
        var num = point.id.substring(5, point.id.length);
        var marker = createMarker(point);
	    map.addOverlay(marker);
	    if (marker.stop == state.stop) {
	        activeMarker = marker;
	    }
	}
	if (activeMarker) {
	    activeMarker.click();
	}
}

function setLocation(loc) {
    map.centerAndZoom(loc, state.scale);
    recalcStops();
}

function explicitRecenter() {
    setAddressDefault();
    recalcStops();
}

// the function to call when you want to re-request stop/time data based on the current map center
function recalcStops() {
    var center = map.getCenterLatLng();
    state.setLocation(center);
    state.save();
    map.clearOverlays();
    map.addOverlay(createMeMarker(center.y, center.x));
    updatePoints(center.y, center.x);
}

var defaultLoc = new GPoint(-71.095359, 42.379917);