var proxyServerName = "";
var proxyServerPort = "";
var ProxyServerPath = "proxy/JSReqHandler.php";

//set up the connection to the geocode server
var geoServerName = "geocode.access.mapquest.com";
var geoServerPort = "80";
var geoServerPath = "mq";
var geoExec = new MQExec(geoServerName, geoServerPath, geoServerPort, proxyServerName, ProxyServerPath, proxyServerPort );

//set up the connection to the route search server
var routeServerName = "route.access.mapquest.com";
var routeServerPort = "80";
var routeServerPath = "mq";
var routeExec = new MQExec(routeServerName, routeServerPath, routeServerPort, proxyServerName, ProxyServerPath, proxyServerPort );

//set up the connection to the Spatial search server
var spatServerName = "spatial.access.mapquest.com";
var spatServerPort = "80";
var spatServerPath = "mq";
var searchExec = new MQExec(spatServerName, spatServerPath, spatServerPort, proxyServerName, ProxyServerPath, proxyServerPort );

var startIcon = new MQMapIcon();
var endIcon = new MQMapIcon();

var startLocation; // used for proximity search
var endLocation;
	
var session = new MQSession();	
var sessId = routeExec.createSessionEx(session);

var myMap = null;

function geocodeAddress() {
    // pass in MQAddress object or street,city,state,zip strings
    if (arguments.length == 4) {
        // create a MQGeoAddress Object
        var address = new MQAddress();
        address.setStreet(arguments[0]);
        address.setCity(arguments[1]);
        address.setState(arguments[2]);
        address.setPostalCode(arguments[3]);
    } else if (arguments.length == 1) {
        var address = arguments[0];
    } else {
        alert('Error in function geocodeAddress(): missing arguments');
    }
    var gaCollection = new MQLocationCollection();
    geoExec.geocode(address, gaCollection);
    if (gaCollection.getSize() == 0) {
        //alert('ERROR: Could not geocode this address: ' + address.getStreet() + ' ' + address.getCity() + ', ' + address.getState() + ' ' + address.getPostalCode());
        return 0;
    } else {
        return gaCollection.get(0);
    }
}

function Location(name, addr, city, state, zip) {
    this.name = name;
    this.mqAddr = new MQAddress();
    this.mqAddr.setStreet(addr);
    this.mqAddr.setCity(city);
    this.mqAddr.setState(state);
    this.mqAddr.setPostalCode(zip);
}

Location.prototype.getMqAddr = function() {
    return this.mqAddr;
};

Location.prototype.getGeoAddr = function() {
    if (this.geoAddr) {
        // return it
    } else if (this.latLng) {
        this.geoAddr = new MQGeoAddress();
        this.geoAddr.setMQLatLng(new MQLatLng(this.latLng.getLatitude(), this.latLng.getLongitude()));
    } else {
        this.geoAddr = geocodeAddress(this.mqAddr);
        if (this.geoAddr) {
            this.latLng = this.geoAddr.getMQLatLng();
        }
    }
    return this.geoAddr;
};

Location.prototype.setPoi = function(poi) {
    this.poi = poi;
};

Location.prototype.getPoi = function() {
    return this.poi || null;
};

Location.prototype.print = function() {
    return this.mqAddr.getStreet() + ' ' + this.mqAddr.getCity() + ', ' + this.mqAddr.getState() + ' ' + this.mqAddr.getPostalCode();
};

Location.prototype.alert = function() {
    var msg = ["Location\n============================\n"];
    msg.push('Constructor: ' + this.constructor + '\n');
    msg.push('Name: ' + this.name + '\n');
    msg.push('Address:\n');
    msg.push(this.mqAddr.getStreet() + '\n');
    msg.push(this.mqAddr.getCity() + '\n');
    msg.push(this.mqAddr.getState() + '\n');
    msg.push(this.mqAddr.getPostalCode() + '\n');
    msg.push('Coords: ' + this.latLng + '\n');
    msg.push((this.poi) ? 'Poi: yes' : 'Poi: no');
    alert(msg.join(''));
};

function Store(name, addr, city, state, zip, driveThru, storePage, distance, latLng) {
    // this inherits methods from Location()
    this.name = name;
    this.mqAddr = new MQAddress();
    this.mqAddr.setStreet(addr);
    this.mqAddr.setCity(city);
    this.mqAddr.setState(state);
    this.mqAddr.setPostalCode(zip);
    this.driveThru = driveThru;
    this.storePage = storePage;
    this.distance = parseFloat(distance);
    this.latLng = latLng;
};
Store.prototype = new Location();

var storeLocations = new Array();

function setMapSize() {
    var minW = 395;
    var minH = 440;
    var maxW = 980;
    var maxH = 650;
    var pageW = getBrowserSize().getWidth();
    var pageH = getBrowserSize().getHeight();
    if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1) { // adjust for scrollbar in firefox
        pageW -= 15;
    }
    var mapW = (pageW <= 780) ? minW : (pageW > 1365) ? maxW : pageW - 385;
    var mapH = (pageH <= 600) ? minH : (pageH > 800) ? maxH : pageH - 160;
    myMap.setSize(new MQSize(mapW, mapH));
    myMap.bestFit();
    document.getElementById("all").style.width = mapW + 365;
    document.getElementById('mapWindow').style.width = mapW;
    document.getElementById('tabWindow').style.height = mapH;
}

function startMap() {
    myMap = new MQTileMap(document.getElementById('mapWindow'), 5, new MQLatLng(42.26, -71.82));
    setMapSize();


    myZControl = new MQLargeZoomControl(myMap);
    myMap.addControl(myZControl, new MQMapCornerPlacement(MQMapCorner.TOP_LEFT, new MQSize(10,20)));
    myVControl = new MQViewControl(myMap);
    myMap.addControl(myVControl, new MQMapCornerPlacement(MQMapCorner.TOP_LEFT, new MQSize(110,0)));

    var browser = new BrowserDetectLite();
    if (!(browser.isIE6up || browser.isFF15up || browser.isSafari2up)) {
        document.getElementById('formWindow').innerHTML = '<br><br><p class="error">It seems that the web browser you are using doesn\'t support our advanced locator feature.  You may wish to download a newer browser for an even better Honey Dew web experience.</p><p class="error">Please <a href="/aboutus/locator.html">click here</a> to use our store locator for legacy browsers.</p>';
    }
}

function clearMap() {
    myMap.removeAllPois();
    myMap.removeRouteHighlight();
}

function clearStores() {
    document.getElementById("storeList").innerHTML = '';
    storeLocations = new Array();
}

function clearDirections() {
    document.getElementById("directions").innerHTML = '';
}

function refreshMappedStores() {
    for (var i=0; i < storeLocations.length; i++) {
        myMap.addPoi(storeLocations[i].getPoi());
    }
    myMap.bestFit();
}

function submitForm() {
    clearMap();
    clearStores();
    clearDirections();

    // get addresses from submission
    init_route();
}

function init_route() {
    var formObj = document.routeForm;

    if (formObj.street1.value || formObj.city1.value || formObj.state1.value || formObj.postalcode1.value) {
        startLocation = new Location('Start', formObj.street1.value, formObj.city1.value, formObj.state1.value, formObj.postalcode1.value);
        var ga = startLocation.getGeoAddr();
        if (!ga) {
            alert('We are unable to geocode your Start address. Please try another address.');
            return
        }
        var poi = new MQPoi(ga.getMQLatLng());
        poi.setInfoTitleHTML(startLocation.name);
        poi.setInfoContentHTML(startLocation.print());
        startLocation.setPoi(poi); // save poi
    } else {
        startLocation = null;
    }
    if (formObj.street2.value || formObj.city2.value || formObj.state2.value || formObj.postalcode2.value) {
        endLocation = new Location('End', formObj.street2.value, formObj.city2.value, formObj.state2.value, formObj.postalcode2.value);
        var ga = endLocation.getGeoAddr();
        if (!ga) {
            alert('We are unable to geocode your End address. Please try another address.');
            return
        }
        var poi = new MQPoi(ga.getMQLatLng());
        poi.setInfoTitleHTML(endLocation.name);
        poi.setInfoContentHTML(endLocation.print());
        endLocation.setPoi(poi); // save poi
    } else {
        endLocation = null;
    }

    if (startLocation && endLocation) {
        // get route
        var routeRes = doRoute([startLocation, endLocation], null);
        
        // set up the SearchCriteria and find stores
        var sCriteria = new MQCorridorSearchCriteria();
        sCriteria.setShapePoints(routeRes.getShapePoints());
        sCriteria.setMaxMatches(20); // we get all results, then sort than give the closest stores limited by users value
        sCriteria.setCorridorWidth(document.getElementById('radius').value);
        var searchRes = new doSearch(sCriteria);

        // add stores to page
        makeStoreResults(searchRes);
    } else if (startLocation) {
        //set up the SearchCriteria and find stores
        var sCriteria = new MQRadiusSearchCriteria();
        sCriteria.setMaxMatches(20); // we get all results, then sort than give the closest stores limited by users value
        sCriteria.setRadius(document.getElementById('radius').value);
        sCriteria.setCenter(startLocation.latLng);
        var searchRes = doSearch(sCriteria);

        // add origin to map
        myMap.addPoi(startLocation.getPoi());

        // add stores to page
        makeStoreResults(searchRes);
    } else {
        alert("error in form");
    }
}

function doRoute(locations, storeIndex) {
    var rRes = new MQRouteResults();
    var wayPoints = new MQLocationCollection();
    var boundBox = new MQRectLL(new MQLatLng(),new MQLatLng());
    var routeOpt = new MQRouteOptions();
    routeOpt.setMaxShapePointsPerManeuver(75);

    // remove previous routes and stores
    clearMap();
    
    // setup waypoints for route and add waypoints to map
    for (var i = 0; i < locations.length; i++) {
        wayPoints.add(locations[i].getGeoAddr());
        myMap.addPoi(locations[i].getPoi());
    }

    routeExec.doRoute(wayPoints, routeOpt, rRes, sessId, boundBox);

    // add route highlight to map
    myMap.addRouteHighlight(boundBox, "http://map.access.mapquest.com", sessId, true);
    myMap.bestFit();

    // add directions to the page
    makeDirections(rRes, locations);
    showTab('directions');
    
    return rRes;
}

function doRouteToStore(i) {
    // adds store to collection with start and end(optional) addresses and calls doRoute
    var routePoints = [startLocation, storeLocations[i]];
    if (endLocation) {
        routePoints.push(endLocation);
    }
    doRoute(routePoints, i); // pass index to save route params in storeLocation
}

function makeDirections(rRes, locations) {
    // adds directions to the page
    var myManStr = "";
    var myTrkStr = "";
    var myMinutes = rRes.getTime()/60;
    if (myMinutes > 60) {
    	if (myMinutes/60 == 1) {
    	    var myTotTime = "1 hr ";
    	}
    	else {
    	    var myTotTime = Math.round((myMinutes/60)*100)/100 + " hrs";
    	}
    }
    else {
    	var myTotTime = myMinutes + " min";
    }
    var myDist = Math.round(rRes.getDistance()*100)/100; 
    document.getElementById("TimeDistanceResults").innerHTML = "Total Time: " + myTotTime + "<br>Total Distance: " + myDist + " miles";

    var trekHeaders = ['<h3 class="red">Start</h3>', '<h3 class="red">Enjoy the Local Flavor</h3>', '<h3 class="red">End</h3>'];
    var manCnt = 1;
    for(var i = 0; i < rRes.getTrekRoutes().getSize(); i++){
    	myTrkStr += '<tr><td colspan="3">' + trekHeaders[i] + '<h3>' + locations[i].print() + '</h3></td></tr>';

    	for (var j = 0; j < rRes.getTrekRoutes().get(i).getManeuvers().getSize(); j++) {
    	    myManDist = Math.round(rRes.getTrekRoutes().get(i).getManeuvers().get(j).getDistance()*100)/100;
    	    myTrkStr += '<tr><td valign="top">' + manCnt +  ".</td><td>" + rRes.getTrekRoutes().get(i).getManeuvers().get(j).getNarrative() + '</td><td valign="top">(' + myManDist + "&nbsp;mi)</td></tr>";
            manCnt++;
    	}
    }
    if (i < trekHeaders.length) {
    	myTrkStr += '<tr><td colspan="3">' + trekHeaders[i] + '<h3>' + locations[i].print() + '</h3></td></tr>';
    }
    var obj = document.getElementById("directions");
    obj.innerHTML = "<table>" + myTrkStr + "</table>";
}

function doSearch(sCriteria) {
    //Setup search source - in this case, the Test DB table
    var dbLayerQueryCollection = new MQDBLayerQueryCollection();
    var dbLayerQuery = new MQDBLayerQuery();
    dbLayerQuery.setDBLayerName("MQA.MQ_33851_HD_SHOPS_2008");
    dbLayerQueryCollection.add(dbLayerQuery);
    
    //empty FeatureCollection to hold the search results
    var searchResults = new MQFeatureCollection();
    
    //Search!
    searchExec.search(sCriteria, searchResults, '', dbLayerQueryCollection);
    showTab('stores');
    
    return searchResults;
}

function sortByDistance(results) {
    // sort results by distance
    var sorted = [];
    // put results in array because sorted a feature collection is foobar
    for (var x = 0; x < results.getSize(); x++) {
        sorted[x] = results.get(x);
    }
    for (var i=0; i < sorted.length-1; i++) {
        for (var j=i+1; j < sorted.length; j++) {
            if (sorted[j].getDistance() < sorted[i].getDistance()) {
                var dummy = sorted[i];
                sorted[i] = sorted[j];
                sorted[j] = dummy;
            }
        }
    }
    return sorted
}

function makeStoreResults(searchRes) {
    // add Stores to map and page
    var all_locations = '';
    
    // set up getRecordInfo parameters
    var fields = new MQStringCollection();
    fields.add("address");
    fields.add("city");
    fields.add("state");
    fields.add("postal");
    fields.add("DriveThru");
    fields.add("store_page");
    var dbLayerQuery = new MQDBLayerQuery();
    dbLayerQuery.setDBLayerName("MQA.MQ_33851_HD_SHOPS_2008");
    
    var poi;
    var matchCnt = 0;
    var limit = document.getElementById('maxResults').value;
    var driveThruOnly = document.getElementById('driveThru').checked;
    var sortedRes = sortByDistance(searchRes);
    //Iterate thru the SORETED results, creating POIs
    for( var i=0; i < sortedRes.length; i++) {
        if (matchCnt == limit) { break }

        resultPoint = sortedRes[i];

        // get store info from db
        var recordSet = new MQRecordSet();
        var keyCollection = new MQStringCollection();
        keyCollection.add(resultPoint.getKey());
        searchExec.getRecordInfo(fields, dbLayerQuery, recordSet, keyCollection);

        var addr = recordSet.getField("address");
        var city = recordSet.getField("city");
        var state = recordSet.getField("state");
        var zip = recordSet.getField("postal");
        var driveThru = recordSet.getField("DriveThru");
        var storePage = recordSet.getField("store_page");
        var distance = Math.round(resultPoint.getDistance()*100)/100;
        var latLng = resultPoint.getCenterLatLng();
        var name = resultPoint.getName();
        
        if (!driveThruOnly || driveThru == 'Yes') { // if driveThruOnly check driveThru value in recordSet
            poi = new MQPoi(latLng);
            var hdIcon = new MQMapIcon();
            hdIcon.setImage("images/hd_icon.gif",50,50,true,false);
            poi.setIcon(hdIcon);
            poi.setInfoTitleHTML(name);
            var infoHTML = [addr,
                            '<br/>',
                            city, ', ', state, ' ', zip,
                            '<br/>Drive Thru: ', driveThru,
                            '<br/>Distance: ', distance,
                            '<br/><br/><a href="#" onclick="doRouteToStore(', i, ');return false;">get directions</a>',
                            ];
            if (storePage) {
              infoHTML.push('<br/><br/><a href="/stores/' + storePage + '">View Local Coupons</a>');
            }
            infoHTML.push('</p>');
            poi.setInfoContentHTML(infoHTML.join(''));
            poi.setKey(resultPoint.getKey());
            myMap.addPoi(poi);
            
            var store = new Store(name, addr, city, state, zip, driveThru, storePage, distance, latLng);
            store.setPoi(poi);
            storeLocations.push(store);
            matchCnt++;
        }
    }
    
    for( var i = 0; i < storeLocations.length; i++){
        all_locations += '<h3>' + storeLocations[i].mqAddr.getStreet()  + ' ' + storeLocations[i].mqAddr.getCity() + ', ' + storeLocations[i].mqAddr.getState() + ' ' + storeLocations[i].mqAddr.getPostalCode() + '</h3><p>Drive Thru: ' + storeLocations[i].driveThru + '<br>Distance: ' + storeLocations[i].distance + '<br><a href="#" onclick="doRouteToStore(' + i + ');return false;">get directions</a><br><br></p>';
    }
    
    var obj = document.getElementById("storeList");
    obj.innerHTML = all_locations;
    
    //Best-Fit the map to the results
    myMap.bestFit();
}

function showTab(clicked) {
    var tabs = ['form', 'stores', 'directions'];
    for (var j=0; j < tabs.length; j++) {
        var tab = tabs[j];
        if (clicked == tab) {
            document.getElementById(tab + 'Tab').src = "/images/" + tab + "TabOn.png";
            document.getElementById(tab + 'Window').style.display = "block";
        } else {
            document.getElementById(tab + 'Tab').src = "/images/" + tab + "TabOff.png";
            document.getElementById(tab + 'Window').style.display = "none";
        }
    }
}
