//39.537, -119.788 is I80 & Hwy 395 intersection 
var center_latlng = new GLatLng (39.537, -119.788);
//var search_latlng = new GLatLng (39.525, -119.78); // off center
var search_latlng = new GLatLng (39.537, -119.788);
var startZoom = 13;
var radius = 1.5;
var bedrooms = "09"; // any
var search_address = "";

var map;
var geocoder;
var iter = 0;
var max_iter = 120;
//max_iter = 2; // for speeding up debugging
// Start from today
var cur_date = daysAgo (0);
//cur_date = '2007-07-19'; // for debugging, but doesn't work with "ago options"

var last_search_date = daysAgo (30); 

var request_date = cur_date;
var request_index = 0;
var icons = new Array ();

var user_id = 0;
var user_name = "";
var marker_window_showing = false;
var marker_quote = 1;
var d1, d2;
var comp_file = 'retrieve_markers.php';
var oodle_file = 'retrieve_oodle_markers.php';

var search_overlays = new Array ();

// Oodle variables
var cur_oodle_ad = 0;
var oodle_total = 0;
var oodle_icons = new Array ();

var x = new Array ( 0,  0, -1, -1, -1,  0,  1,  1,  1,  0, -1, -2, -2, -2, -1,  0,  1,  2,  2,  2,  1,  0, -1, -2, -3,
									 -3, -3, -2, -1,  0,  1,  2,  3,  3,  3,  2,  1,  0, -1, -2, -3, -4, -4, -4, -4, -4, -3, -2, -1,  0,
										1,  2,  3,  4,  4,  4,  4,  4,  3,  2,  1,  0, -1, -2, -3, -4, -5, -5, -5, -5, -5, -4, -3, -2, -1,
										0,  1,  2,  3,  4,  5,  5,  5,  5,  5,  4,  3,  2,  1,  0, -1, -2, -3, -4, -5, -6, -6, -6, -6, -6);
var y = new Array ( 0, -1, -1,  0,  1,  1,  1,  0, -1, -2, -2, -1,  0,  1,  2,  2,  2,  1,  0, -1, -2, -3, -3, -2, -1,
										0,  1,  2,  3,  3,  3,  2,  1,  0, -1, -2, -3, -4, -4, -4, -3, -2, -1,  0,  1,  2,  3,  4,  4,  4,
										4,  4,  3,  2,  1,  0, -1, -2, -3, -4, -5, -5, -5, -5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5,  5,
										5,  5,  5,  4,  3,  2,  1,  0, -1, -2, -3, -4, -5, -6, -6, -6, -6, -5, -4, -3, -2, -1,  0,  1,  2);
var lat_points = new Array ();
var lng_points = new Array ();
var marker_count = 0;

var search_count = 0;

window.onload = init;

function init() {
		geocoder = new GClientGeocoder();
    map = new GMap2(document.getElementById("map"));
		map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(center_latlng, startZoom);
		map.enableContinuousZoom();
		map.enableScrollWheelZoom();
		map.addControl(new GScaleControl(90)); // displays a scale bar with a maximum length of x pixels, where x defaults to 125. 

    //----- Stop page scrolling if wheel over map ----
    function wheelevent(e) {
        if (!e)
						e = window.event;
        if (e.preventDefault)
						e.preventDefault();
        e.returnValue = false;
    }
		GEvent.addDomListener(map.getContainer(), "DOMMouseScroll", wheelevent);
		map.getContainer().onmousewheel = wheelevent; 

    GEvent.addListener(map, 'click', function(overlay, latlng) {
				//only perform the click if the window is closed and the click was directly on the map.
				if(!overlay) {
						//alert (search_latlng);
						openSearchWindow (latlng, 0)
				}
		});

		addCustomControls ();

	  drawSearchArea ();

		map.openInfoWindow (search_latlng, "Click on any dot to see rental details.<BR>"
				+ "Click somewhere on the map to start a new search.<BR>"
				+ "Color of dots represents price per month.");

//		retrieveOodleAds (); // 8/2/2009 noticed error: Failed opening required 'XML/RPC.php'

    retrieveCOMPMarkers ();	
}

function openSearchWindow (new_latlng, need_to_center) {
		// See if point is inside of the Greater Reno Area
		if (new_latlng.lat() < 40 && new_latlng.lat() > 38.3 && new_latlng.lng() > -120.4 && new_latlng.lng() < -117.6) {			
				if (need_to_center)
						map.setCenter (new_latlng);

				// See if marker window is opened
				if (marker_window_showing == true) {
						//alert ('marker_window_showing == true');
						map.closeInfoWindow();
						marker_window_showing = false;
				} else {
						// Create an HTML DOM form element
						var inputForm = document.createElement ("form");
						inputForm.setAttribute ("action", "");
						inputForm.setAttribute ("id", "search_form");
						inputForm.onsubmit = function() {
								search_latlng = new_latlng;
								radius = parseFloat(document.getElementById ("radius").value);
								last_search_date = document.getElementById ("age").value;
								bedrooms = document.getElementById ("brm").value;
								// Limit number of details for unregistered users
								if (user_id == 0)
										marker_quote = 0;
								storeMarker();
								return false;
						};
		
						var big_miles = '3.0';
						if (user_id == 1)
								big_miles = '15.0';
						inputForm.innerHTML = '<fieldset style="width:180px;">'
								+ '<legend>Select Search Creteria</legend>'
								+ '<label for="radius">Radius: </label>'
								+ '<select id="radius" style="width:65%">'
								+ '<option value = "0.05">0.05 miles</option>'
								+ '<option value = "0.3">0.3 miles</option>'
								+ '<option value = "0.5">0.5 miles</option>'
								+ '<option value = "1.0">1.0 miles</option>'
								+ '<option value = "1.5" selected="selected">1.5 miles</option>'
								+ '<option value = "2.0">2.0 miles</option>'
								+ '<option value = "2.5">2.5 miles</option>'
								+ '<option value = "' + big_miles + '">' + big_miles + ' miles</option>'
								+ '</select><br>'
								+ '<label for="age">Dates:   </label>'
								+ '<select id="age" style="width:68%">'
								+ '<option value = "2007-06-19">All dates</option>'
								+ '<option value = "' + daysAgo (30)  + '">1 month back</option>'
								+ '<option value = "' + daysAgo (61)  + '">2 months back</option>'
								+ '<option value = "' + daysAgo (91)  + '" selected="selected">3 months back</option>'
								+ '<option value = "' + daysAgo (182) + '">6 months back</option>'
								+ '<option value = "' + daysAgo (273) + '">9 months back</option>'
								+ '<option value = "' + daysAgo (365) + '">1 year back</option>'
								+ '<option value = "' + daysAgo (730) + '">2 years back</option>'
								+ '</select><br>'
								+ '<label for="brm">Bedrooms:   </label>'
								+ '<select id="brm" style="width:53%">'
								+ '<option value = "09" selected="selected">Any</option>'
								+ '<option value = "11">1</option>'
								+ '<option value = "22">2</option>'
								+ '<option value = "33">3</option>'
								+ '<option value = "44">4</option>'
								+ '<option value = "12">1 or 2</option>'
								+ '<option value = "23">2 or 3</option>'
								+ '<option value = "34">3 or 4</option>'
								+ '<option value = "13">1 to 3</option>'
								+ '<option value = "14">1 to 4</option>'
								+ '<option value = "24">2 to 4</option>'
								+ '<option value = "29">2 or more</option>'
								+ '<option value = "39">3 or more</option>'
								+ '<option value = "49">4 or more</option>'
								+ '<option value = "59">5 or more</option>'
								+ '</select>'
								+ '<input type="submit" value="Search Rental Rates"/>'
								+ '</fieldset>';
		
						map.openInfoWindow (new_latlng, inputForm);
				}
		} else {
				alert("Warning! Address is outside of the Greater Reno Area or incorrectly entered.");
		}

}
// 11153 Green Mountain, 89506

function storeMarker () {
    // Try stopping previous requests
    request_date = last_search_date;
        
    var getVars = "?r=" + radius + "&b=" + bedrooms + "&lng=" + search_latlng.lng() + "&lat=" + search_latlng.lat()
				+ "&u=" + user_name + "&a=" + decodeURIComponent (search_address);

    var request = GXmlHttp.create();

    // Open the request to storeMakres.php on your server
    request.open('GET', 'RentalRates/storeMarker.php' + getVars, true);
    request.onreadystatechange = function() {
       if (request.readyState == 4) {
            //the request in complete

            var xmlDoc = request.responseXML;

            //retrieve the root document element (response)
            var responseNode = xmlDoc.documentElement;

            //retrieve the type attribute of the node
            var type = responseNode.getAttribute("type");

            //retrieve the content of the responseNode
            var content = responseNode.firstChild.nodeValue;

            //check to see if it was an error or success
            if(type!='success') {
                alert(content);
            } else {
                search_count++;
								drawSearchArea ();
								retrieveOodleAds ();
								retrieveCOMPMarkers ();
           }
       }
    }
    request.send(null);
    return false;
}

function drawSearchArea () {
		//alert (search_overlays.length);
		// Remove previous markers
		for (var overlay_i in search_overlays) {
				map.removeOverlay (search_overlays [overlay_i]);
		}
		search_overlays.length = 0;
	
    // Create a new marker for circle and add its info window.
    createMarker (search_latlng, 'Radius: ' + radius + ' mile(s)', null, '', 'copms_center');
    map.closeInfoWindow ();

    // Convert radius from miles to kilometers
 		// Draw circle radius a little bigger to cover all markers
		drawCircle (search_latlng, (radius + 0.07) / 0.62, 40);

		// Reset marker count
		marker_count = 0;

    request_date = cur_date;
}

function retrieveCOMPMarkers () {
    var request = GXmlHttp.create();
    window.status = request_date + ' ' + request_index;
    // tell the request where to retrieve data from.
    request.open('GET', 'RentalRates/' + comp_file + '?d=' + request_date + '&ld=' + last_search_date + '&i=' + request_index
        + '&la=' + search_latlng.lat() + '&ln=' + search_latlng.lng() + '&r=' + radius + "&b=" + bedrooms + '&u=' + user_id
				+ '&sr=' + search_count, true);
    
    // tell the request what to do when the state changes.
    request.onreadystatechange = function() {
				if (request.readyState == 4) {
						processResults (request, 'comps');
						if (request_date != last_search_date)
								request_date = d1;
						request_index = d2;
						// Now that the the previous request is complete, do new request
						// Stop processing once specified day is reached
						if (++iter < max_iter) {// for debugging to spead things up
								if (Date.parse (request_date.replace (/-/g, "/")) > Date.parse (last_search_date.replace (/-/g, "/")))
										setTimeout ("retrieveCOMPMarkers ()", 1000); // wait a little before making new request
						} else
								iter = 0;
				} //if
		} //function
		request.send(null);
}

function retrieveOodleAds () {
		var request = GXmlHttp.create();
		window.status = cur_oodle_ad;
		// tell the request where to retrieve data from.
		request.open('GET', 'RentalRates/' + oodle_file + '?i=' + cur_oodle_ad
								 + '&c=housing/rent/home' + '&la=' + search_latlng.lat() + '&ln=' + search_latlng.lng()
								 + '&r=' + radius + "&b=" + bedrooms + '&sr=' + search_count, true);
		
		//tell the request what to do when the state changes.
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
					processResults (request, 'oodle');
					cur_oodle_ad = parseInt (d1, 10);
					oodle_total = parseInt (d2, 10);
					//alert ('cur_oodle_ad=' + cur_oodle_ad + ' oodle_total=' + oodle_total);
					// Now that the the previous request is complete, do new request
					if (++iter < max_iter) {// for debugging to spead things up
							if (cur_oodle_ad < oodle_total) {  // Make sure these are integers, otherwise "402" > "3306" as strings
								setTimeout ("retrieveOodleAds ()", 1000); // wait a little before doing it again
							} else {
								//alert ('All done!');
							}
					} else
							iter = 0;
		
			} //if
		} //function
		request.send(null);			
}

function processResults (request, marker_type) {	
	var xmlObj;
	var xmlDoc = request.responseXML;
	if (xmlDoc)
		xmlObj = xmlDoc.documentElement;
	if (!xmlObj) {
		if (user_id == 1) alert ('xmlObj = 0');
	}
	else {
		var result_status = xmlObj.getElementsByTagName("rs"); // rs = result_status
		if (!result_status[0]) {
				//if (user_id == 1)
				//		alert ('result_status[0] = 0');
		}	else {
			var request_status = parseInt (result_status[0].getAttribute("st")); // st = status
			d1 = result_status[0].getAttribute("d1");
			// This will also get rid of results of prevoius search
			if (request_status == search_count) {
				d2 = result_status[0].getAttribute("d2");
				//alert (request_status + ' ' + d1 + ' ' + d2);
					
				var markers = xmlObj.getElementsByTagName("m"); // m = marker
					// It's possible to have no marker at all
					for (var i = 0; i < markers.length; i++) {
						var marker_lng = parseFloat (markers[i].getAttribute("Ln"));
						var marker_lat = parseFloat (markers[i].getAttribute("La"));
						var price = parseInt (markers[i].getAttribute("Pr"), 10); // Pr = Price
						var br = parseInt (markers[i].getAttribute("BR"), 10);
						// Decode header
						var title = decodeURIComponent (markers[i].getAttribute("Tl")); // Tl = Title
						// Don't change format of date, since it's used to get post details
						var date = markers[i].getAttribute("Dt"); // Dt = Date yyyy-mm-dd
						// Create date_string in the format mm/dd/yyyy
						var date_fields = date.split ("-");
						var date_string = date_fields[1] + "/" + date_fields[2] + "/" + date_fields[0];
						//alert ("date_string = " + date_string); // hard to get rid of this alert
						var post_id = markers[i].getAttribute("ID");
						// URL is coming only from OOdle
						var post_url = decodeURIComponent (markers[i].getAttribute("URL"));
						if (price && marker_lng && marker_lat) {
						var marker_title = '$' + price + '/mo';
						if (marker_quote > 0) {
							if (br > 0) {
								marker_title += ', ' + br + ' bd';
								if (br > 1)
									marker_title += 's';                            
								}
								var title_link = '<a href="';
								if (post_id > 0)
								  title_link += 'RentalRates/pdz.php?i=' + post_id + '&d=' + date + '&u=' + user_id;
								else // It's Oodle's ad, just use URL
									title_link += post_url;
										
								title_link += '" target="_blank">' + title + '</a>';
								var html = '<div><b>' + marker_title + '</b></div><div>'
												 + title_link + '</div><div>Posted: ' + date_string + '</div>';
								marker_title += ', ' + date_string;
							}
							else {
								// Only unregistered users will get here
								var html = '<div><b><a href="user">Login</a> or '
												 + '<a href="user/register">Register</a> to see full details.<BR>'
												 + "It's free and easy.</div>";
							}
							var marker_latlng = makeUniquePoint (marker_lat, marker_lng);
							createMarker (marker_latlng, html, price, marker_title, marker_type);
							marker_count++;
						}           
					} //for
				} // if
			} // if
		}
}
 
function makeUniquePoint (lat, lng) {
	var point_exists = 0;
	var multiplier_lat = 8500; // this determines how far apart are markers
	var multiplier_lng = 7000; 
	var original_lat = parseInt (lat * multiplier_lat);
	var original_lng = parseInt (lng * multiplier_lng);
  var number_of_changes = x.length; 
	var run_out = 0;
	for (var change = 0; change < number_of_changes; change++) {
		point_exists = 0;
		var discrete_lat = parseInt (lat * multiplier_lat);
		var discrete_lng = parseInt (lng * multiplier_lng);
		// Go through all added markers so far and see if there's already one at the current location
		for (var m = 0; m < marker_count; m++) {
			if (discrete_lat == lat_points [m] && discrete_lng == lng_points [m]) { 
				//alert ("Point like this already exists:" + discrete_lat + ", " + discrete_lat);
				// Point like this already exists, change location randomly
		    // Instead of modifying location permanently, just change location on the map
				lat = (original_lat + y [change]) / multiplier_lat;
				lng = (original_lng + x [change]) / multiplier_lng;
				point_exists = 1;
				break;
			}
		}
		// Get out of this loop if no markers are at this position
		if (point_exists == 0)
			break;
		else {
			// if we ran out of changes, move origin and try more changes
			if (change == number_of_changes - 1) {
			  // Start over
				change = 0;
				run_out++;
				original_lat += 2 * y [run_out];
				original_lng += 2 * x [run_out];
			}
		}
	}
	
	// Store descrete marker location
	lat_points [marker_count] = parseInt (lat * multiplier_lat)
	lng_points [marker_count] = parseInt (lng * multiplier_lng)

  return new GLatLng (lat_points [marker_count] / multiplier_lat, lng_points [marker_count] / multiplier_lng);
}

function createMarker (marker_latlng, html, price_string, marker_title, marker_type) {
		//alert (marker_type);
		var marker;
		var marker_opts;
		var price = parseInt (parseInt (price_string, 10) / 100, 10) * 100;
		if (price > 2700) price = 2700;
		if (price < 300) price = 300;
		
		if (marker_type == 'oodle') {			
				var icons_type = 'files/Icons_oodle/';
				// Define new icon only if it doesn't exist already
				if (oodle_icons [price] == undefined) {
						oodle_icons [price] = new GIcon();
						var image_url = icons_type + price + '.png';
						oodle_icons [price].image = image_url; 
						oodle_icons [price].iconSize = new GSize(16, 16);
						oodle_icons [price].iconAnchor = new GPoint(8, 8);
						oodle_icons [price].infoWindowAnchor = new GPoint(15, 1);
				}
				marker_opts = { icon : oodle_icons [price],
												title : marker_title };
		} else {
				var icons_type = 'files/Icons_round/';
				// Define new icon only if it doesn't exist already
				if (icons [price] == undefined) {
						icons [price] = new GIcon();
						var image_url = icons_type + price + '.png';
						icons [price].image = image_url; 
						icons [price].iconSize = new GSize(16, 16);
						icons [price].iconAnchor = new GPoint(8, 8);
						icons [price].infoWindowAnchor = new GPoint(15, 1);
				}
				marker_opts = { icon : icons [price],
												title : marker_title };
		}
		
		if (marker_type == 'copms_center') {
				marker = new GMarker(marker_latlng);
		} else {
				marker = new GMarker(marker_latlng, marker_opts);
		}
		GEvent.addListener(marker, 'click', function() {
				marker.openInfoWindowHtml(html, { noCloseOnClick : true });
		});
		GEvent.addListener(marker, 'infowindowopen', function() {
				marker_window_showing = true;
		});
		GEvent.addListener(marker, 'infowindowbeforeclose', function() {
				marker_window_showing = false;
		});

		map.addOverlay (marker);
		// Save markers so that later they could be removed from the map
		if (marker_type == 'comps' || marker_type == 'copms_center' || marker_type == 'oodle')
				search_overlays [search_overlays.length] = marker;
}

function addCustomControls () {
    // Explain heatmap
		function HeatMapLegendControl() {}
		HeatMapLegendControl.prototype = new GControl();
		HeatMapLegendControl.prototype.initialize = function() {
				var contents = document.createElement("div");
				contents.innerHTML='<img style="border:none;" src = "files/Heat_map_legend.png" alt="Rental Rates HeatMap Legend"/>';
				document.getElementById('map').appendChild(contents);
				return contents;
		}
		HeatMapLegendControl.prototype.getDefaultPosition=function(){
				return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 40));
		}
		HeatMapLegendControl.prototype.selectable=function(){return true};
		HeatMapLegendControl.prototype.printable=function(){return true};
		map.addControl(new HeatMapLegendControl());

    // Explain Icons
		function IconLegendControl() {}
		IconLegendControl.prototype = new GControl();
		IconLegendControl.prototype.initialize = function() {
				var contents = document.createElement("div");
				contents.innerHTML='<img style="border:none;" src = "files/Icon_legend.png" alt="Rental Rates Icons Legend"/>';
				document.getElementById('map').appendChild(contents);
				return contents;
		}
		IconLegendControl.prototype.getDefaultPosition=function(){
				return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(70, 35));
		}
		IconLegendControl.prototype.selectable=function(){return true};
		IconLegendControl.prototype.printable=function(){return true};
		map.addControl(new IconLegendControl());

		// Create Search control		
		function SearchControl() {}
		SearchControl.prototype = new GControl();
		SearchControl.prototype.initialize = function() {
				var default_search_value = "Enter here: address, city, state  OR  just zip code";

				var search_form = document.createElement("form");
				search_form.innerHTML = '<input type="text" id="search_address" value="' + default_search_value
						+ '" size="50" onfocus="if (this.value==\'' + default_search_value + '\') this.value=\'\';">'
						+ '<input type="submit" value="Find Rental Rates">';
        search_form.setAttribute("action", "");
				search_form.onsubmit = function() {
						search_address = document.getElementById("search_address").value;
						//alert("'" + search_address + "'");
						if (search_address != default_search_value && search_address != "") {
								
								geocoder.getLatLng (search_address, function (new_latlng) {
										if(new_latlng === null) {
												alert("Can't find address '" + search_address + "'");
										} else {
												openSearchWindow (new_latlng, 1);
										}
								});
 						}
						return false;
				};
				document.getElementById('map').appendChild (search_form);
				return search_form;
		}
		SearchControl.prototype.getDefaultPosition=function() {
				return new GControlPosition(G_ANCHOR_TOP_LEFT,new GSize(70,7))
		}
		SearchControl.prototype.printable=function() {return true};
		SearchControl.prototype.selectable=function() {return true};
		map.addControl(new SearchControl());
}

function drawCircle(center, circle_radius, nubmer_of_segments)
{
  //calculating km/degree
	var latConv = center.distanceFrom(new GLatLng(center.lat()+0.1, center.lng()))/100;
	var lngConv = center.distanceFrom(new GLatLng(center.lat(), center.lng()+0.1))/100;

	var points = [];
	var step = parseInt(360/nubmer_of_segments, 10) || 10;
	for(var i=0; i<=360; i+=step)
	{
    var pint = new GLatLng(center.lat() + (circle_radius/latConv * Math.cos(i * Math.PI/180)), center.lng() + 
    (circle_radius/lngConv * Math.sin(i * Math.PI/180)));
    points.push(pint);
	}
	fillColor = "#555555";
  fillOpa = 0.2;
  strokeOpa = 0.5;
  strokeColor = "#555555";
	strokeWidth = 2;
  var opts = {clickable : false};
	var poly = new GPolygon(points, strokeColor, strokeWidth, strokeOpa, fillColor, fillOpa, opts);
	map.addOverlay(poly);
	search_overlays [search_overlays.length] = poly;
}

function daysAgo (number_of_days)
{
		var one_day_in_ms = 60 * 1000 *60 * 24;
		var temp_date = new Date ();
		temp_date.setTime (temp_date.getTime () - one_day_in_ms * number_of_days);
		var temp_month = temp_date.getMonth () + 1; // months start with 0, don't move to next line to avoid string addition
		var days_ago_string = temp_date.getFullYear () + '-' + temp_month + '-' + temp_date.getDate();
		return days_ago_string;
}
