
function DOMElement( element_type, class_name ) {
	var element = document.createElement(element_type);
	element.setAttribute('class',class_name);
	element.className = class_name;
	return element;
}

function makeButton( value ) {
	var button = DOMElement('input','');
	button.setAttribute('type','button');
	button.setAttribute('value',value);
	return button;
}

function confirmDialog( message, title, confirm_action, manager ) {
	var div = DOMElement('div','window_content');
	var center = DOMElement('center','');
	div.style.width = '300px';
	
	var yes = makeButton('yes');
	var no = makeButton('no');
	
	center.appendChild(yes);
	center.appendChild(no);
	
	div.appendChild(document.createTextNode(message));
	div.appendChild(center);
	
	var close_window = manager.makeCloseWindow(manager.openWindow(div,title,null),null);
	yes.onclick = function() {
		if ( confirm_action ) confirm_action();
		close_window();
	};
	no.onclick = function() {
		close_window();
	};
	
	yes.focus();
}

function round( number, precision ) {
	number *= Math.pow(10,precision);
	number = Math.round(number);
	number /= Math.pow(10,precision);
	number = number + '';
	
	if ( number.indexOf('.') < 0 && precision > 0 ) number += '.0';
	while ( number.length - number.indexOf('.') < precision + 1 ) number += '0';
	
	return number;
}

function Road( name, id, length, climb, overlay_color ) {
	this.name = name;
	this.id = id;
	this.length = length;
	this.climb = climb;
	this.overlay_color = overlay_color ? overlay_color : '#0000ff';
	
	this.endpoints = null;
	this.path = null;
	
	Road.prototype.setRoadPath = function( array ) {
		var path_points = new Array();
		for ( var i = 0; i < array.length; ++i ) {
			path_points.push(new GLatLng(parseFloat(array[i].getAttribute('latitude')),
										parseFloat(array[i].getAttribute('longitude'))));
		}
		
		this.path = new GPolyline(path_points,this.overlay_color);
		this.endpoints = new Array();
		if ( path_points.length > 3 ) {
			this.endpoints[0] = path_points[0];
			this.endpoints[1] = path_points[1];
			this.endpoints[2] = path_points[path_points.length-2];
			this.endpoints[3] = path_points[path_points.length-1];
		} else {
			for ( var i = 0; i < path_points.length; ++i )
				this.endpoints[i] = path_points[i];
				
			this.elongateEndpoints();
		}
	};
	
	Road.prototype.elongateEndpoints = function() {
		if ( this.endpoints.length == 3 ) {
			this.endpoints[3] = this.endpoints[2];
			this.endpoints[2] = this.endpoints[1];
		} else {
			this.endpoints[3] = this.endpoints[1];
			this.endpoints[2] = this.endpoints[0];
		}
	};
	
	Road.prototype.getEndpointsByLatLng = function( lat, lng ) {
		var array = new Array();
		
		if ( this.endpoints[0].lat() == lat && this.endpoints[0].lng() == lng ) {
			array.push(this.endpoints[1]);
			array.push(this.endpoints[0]);
		} else {
			array.push(this.endpoints[2]);
			array.push(this.endpoints[3]);
		}
		
		return array;
	};
}

function Direction( direction, distance, climb, road ) {
	this.direction = direction;
	this.distance = distance;
	this.climb = climb;
	this.road = road;
}

function Intersection( name, id, elevation ) {
	this.elevation = Math.round(elevation,1);
	this.id = id;
	this.name = name;
	
	this.marker = null;
	this.options = new Array();
	this.directions = new Array();
	
	Intersection.prototype.getInfoWindow = function() {
		var div = DOMElement('div','info_window');
		var span = DOMElement('span','header');
		span.appendChild(document.createTextNode(this.name));
		div.appendChild(span);
		div.appendChild(document.createElement('br'));
		div.appendChild(document.createTextNode('Elevation: '+this.elevation+' ft'));
		return div;
	};
	
	Intersection.prototype.popOption = function() {
		if ( this.options.length > 0 )
			this.options.pop();
			
		return ( this.options.length + this.directions.length > 0 ? true : false );
	};
	
	Intersection.prototype.getOptionWindow = function( distance, climb, route_builder ) {
		var div = this.getInfoWindow();
		
		if ( this.options.length > 0 )
			div.appendChild(this.getOptionsDiv(distance,climb,route_builder));
		if ( this.directions.length > 0 )
			div.appendChild(this.getDirectionsDiv(route_builder));
			
		return div;
	};
	
	Intersection.prototype.getOptionsDiv = function( distance, climb, route_builder ) {
		var div = DOMElement('div','info_window');
		var b = DOMElement('span','header');
		b.appendChild(document.createTextNode('Use as waypoint'));
		
		div.appendChild(document.createElement('br'));
		div.appendChild(b);
		
		for ( var i = 0; i < this.options.length; ++i )
			div.appendChild(this.makeOptionDiv(i,distance,climb,route_builder));
		
		return div;
	};
	
	Intersection.prototype.makeOptionDiv = function( index, distance, climb, route_builder ) {
		var road = this.options[index];
		
		var div = DOMElement('div','info_window');
		div.appendChild(document.createTextNode('via '+road.name+': '+
												(parseInt((distance+parseFloat(road.length))*100)/100)+' mi, '+
												(climb+parseInt(road.climb))+' ft [ '));
		var a = document.createElement('a');
		a.setAttribute('href','javascript:;');
		a.appendChild(document.createTextNode('use'));
		var n_this = this;
		a.onclick = function() {
			route_builder.selectIntersection(n_this.id,road.id);
		};
		var info = document.createElement('a');
		info.setAttribute('href','javascript:;');
		info.onclick = function() {
			route_builder.showRoadInfo(road.id,n_this.id);
		};
		info.appendChild(document.createTextNode('info'));

		div.appendChild(info);
		div.appendChild(document.createTextNode(' ] [ '));
		div.appendChild(a);
		div.appendChild(document.createTextNode(' ]'));
		
		return div;
	}
	
	Intersection.prototype.getDirectionsDiv = function( route_builder ) {
		var div = DOMElement('div','info_window');
		var b = DOMElement('span','header');
		b.appendChild(document.createTextNode('Directions'));
		
		div.appendChild(document.createElement('br'));
		div.appendChild(b);
		
		for ( var i = 0; i < this.directions.length; ++i ) {
			var d = DOMElement('div','info_window');
			var a = DOMElement('a','');
			var nobr = DOMElement('nobr','');
			a.setAttribute('href','javascript:;');
			a.appendChild(document.createTextNode('clear'));
			a.onclick = this.makeClearFn(route_builder,i);
			d.appendChild(document.createTextNode('At '+(parseInt(this.directions[i].distance*100)/100)+' mi, '+
													this.directions[i].direction+' ('+this.directions[i].climb+' ft) '));
			nobr.appendChild(document.createTextNode('[ '));
			nobr.appendChild(a);
			nobr.appendChild(document.createTextNode(' ]'));
			d.appendChild(nobr);
			div.appendChild(d);
		}
		
		return div;
	};
	
	Intersection.prototype.makeClearFn = function( route_builder, direction ) {
		var n_this = this;
		return function() {
			route_builder.clearFromDirection(n_this.id,direction);
		};
	};
	
	Intersection.prototype.getRoadById = function( id ) {
		for ( var i = 0; i < this.options.length; ++i ) {
			if ( this.options[i].id == id )
				return this.options[i];
		}
		
		return null;
	};
	
	Intersection.prototype.popDirection = function( route_builder ) {
		if ( this.directions.length < 1 )
			return false;
			
		var direction = this.directions.pop();
		
		if ( route_builder ) {
			route_builder.map.removeOverlay(direction.road.path);
			route_builder.decrementAccumulators(direction.road.length,direction.road.climb);
		}
				
		return ( this.directions.length > 0 && this.options.length > 0 );
	};
}

function RouteBuilder( manager, map, tbody, ddirections ) {
	this.manager = manager;
	this.map = map;
	this.radius = 1;
	this.tbody = tbody;
	this.ddirections = ddirections;
	
	this.intersections;
	this.temp_intersections;
	
	this.route;
	
	this.distance = 0;
	this.climb = 0;
	
	this.is_loading = false;
	
	RouteBuilder.prototype.zoomSuccessFn = function() {
		var n_this = this;
		return function() {
			n_this.getNodes();
		};
	};
	
	RouteBuilder.prototype.getNodes = function() {
		if ( this.route && this.route.length > 0 ) {
			// some sort of confirmation...
			var message = 'This will erase all current progress; would you like to continue?';
			var n_this = this;
			confirmDialog(message,'start over',function(){n_this.reallyGetNodes();},this.manager);
			return;
		}
		
		this.reallyGetNodes();
	};
	
	RouteBuilder.prototype.reallyGetNodes = function() {
		this.showLoadWindow();
		
		// fix up the object
		this.intersections = new Array();
		this.route = new Array();
		this.temp_intersections = new Array();
		this.distance = 0.0;
		this.climb = 0;
		var latitude = this.map.getCenter().lat();
		var longitude = this.map.getCenter().lng();
		
		// now for fun gui stuff!
		this.ddirections.style.display = 'none';
		for ( var i = 0; i < this.tbody.childNodes.length; i )
			this.tbody.removeChild(this.tbody.firstChild);
		
		this.map.clearOverlays();
		var ajax_url = '/xml/load.intersections.php?latitude='+latitude+'&longitude='+longitude+'&radius='+this.radius;
		
		var n_this = this;
		var success_fn = function( responseXML, responseText ) {
			responseText = null;
			var points = responseXML.documentElement.getElementsByTagName('intersection');
			
			for ( var i = 0; i < points.length; ++i ) {
				var point = points[i];
				var intersection = new Intersection(point.getAttribute('label'),
													point.getAttribute('id'),
													point.getAttribute('elev'));
				intersection.marker = new GMarker(new GLatLng(parseFloat(point.getAttribute('lat')),
																parseFloat(point.getAttribute('lng'))));
				GEvent.addListener(intersection.marker,'click',n_this.getStartingIntersectionFn(intersection));
				n_this.map.addOverlay(intersection.marker);
				
				n_this.intersections[intersection.id] = intersection;
				n_this.temp_intersections.push(intersection.id);
			}
			
			n_this.stopLoad();
		};
		
		var ajax_request = new ajax(ajax_url,success_fn,null,null);
		ajax_request.connect();
	};
	
	RouteBuilder.prototype.getStartingIntersectionFn = function( intersection ) {
		var n_this = this;
		return function() {
			n_this.startingIntersectionFn(intersection);
		};
	};
	
	RouteBuilder.prototype.startingIntersectionFn = function( intersection ) {
		var div = intersection.getInfoWindow();
		
		var a = DOMElement('a','');
		a.setAttribute('href','javascript:;');
		var n_this = this;
		a.onclick = function() {
			n_this.selectIntersection(intersection.id);
		};
		a.appendChild(document.createTextNode('begin route here'));
		
		this.insertLineBreaks(div,2);
		div.appendChild(document.createTextNode('[ '));
		div.appendChild(a);
		div.appendChild(document.createTextNode(' ]'));
		
		intersection.marker.openInfoWindow(div);
	};
	
	RouteBuilder.prototype.insertLineBreaks = function( element, count ) {
		for ( var i = 0; i < count; ++i )
			element.appendChild(document.createElement('br'));
	};
	
	RouteBuilder.prototype.clearTempIntersections = function() {
		for ( var i = 0; i < this.temp_intersections.length; ++i ) {
			if ( this.intersections[this.temp_intersections[i]] &&
				!this.intersections[this.temp_intersections[i]].popOption() ) {				
				this.map.removeOverlay(this.intersections[this.temp_intersections[i]].marker);
				this.intersections[this.temp_intersections[i]] = null;
			}
		}		
		this.temp_intersections = new Array();
	};
	
	RouteBuilder.prototype.selectIntersection = function( intersection_id, road_id ) {
		GEvent.trigger(this.map.getInfoWindow(),'closeclick');
		
		var intersection = this.intersections[intersection_id];
		this.route.push(intersection_id);
		var road = intersection.getRoadById(road_id);
		this.clearTempIntersections();
		this.map.closeInfoWindow();
		
		GEvent.clearListeners(intersection,'mouseover');
		GEvent.clearListeners(intersection,'mouseout');
		this.intersections[intersection_id] = intersection;
		if ( road ) {
			this.map.addOverlay(road.path);
			var direction = new Direction('',this.distance,this.climb,road);
			direction.direction = this.getMostRecentDirection(road);
			this.intersections[this.route[this.route.length-2]].directions.push(direction);
			this.distance += parseFloat(road.length);
			this.climb += parseInt(road.climb);
			this.ddirections.style.display = 'block';
			this.tbody.appendChild(this.makeLatestDirectionRow());
		}
		
		this.loadNextNodes(intersection);
	};
		
	RouteBuilder.prototype.loadNextNodes = function( intersection ) {
		this.showLoadWindow();
		this.map.removeOverlay(intersection.marker);
		
		var ajax_url = '/include/xml/load.linked.nodes.php?id='+intersection.id;
		var n_this = this;
		var success_fn = function( responseXML, responseText ) {
			responseText = null;
			var roads = responseXML.documentElement.getElementsByTagName('road');
			for ( var i = 0; i < roads.length; ++i ) {
				var road = new Road(roads[i].getAttribute('label'),roads[i].getAttribute('id'),
									roads[i].getAttribute('length'),roads[i].getAttribute('climb'),roads[i].getAttribute('overlaycolor'));
				road.setRoadPath(roads[i].getElementsByTagName('roadpt'));
				
				var tmp_intersection = new Intersection(roads[i].getAttribute('tolabel'),
														roads[i].getAttribute('toid'),
														roads[i].getAttribute('toelev'));
														
				if ( !n_this.intersections[tmp_intersection.id] ) {
					tmp_intersection.marker = new GMarker(new GLatLng(parseFloat(roads[i].getAttribute('tolat')),
																		parseFloat(roads[i].getAttribute('tolng'))));
					n_this.intersections[tmp_intersection.id] = tmp_intersection;
					n_this.map.addOverlay(tmp_intersection.marker);
				}
				
				n_this.temp_intersections.push(tmp_intersection.id);
				n_this.intersections[tmp_intersection.id].options.push(road);
				
				var marker = n_this.intersections[tmp_intersection.id].marker;
				GEvent.clearInstanceListeners(marker);
				GEvent.addListener(marker,'click',n_this.getWaypointInfoWindowFn(tmp_intersection.id));
				GEvent.addListener(marker,'mouseover',n_this.drawWaypointOverlaysFn(tmp_intersection.id));
				GEvent.addListener(marker,'mouseout',n_this.clearWaypointOverlaysFn(tmp_intersection.id));
				
			}
			
			n_this.stopLoad();
		};
		var ajax_request = new ajax(ajax_url,success_fn,null,null);
		ajax_request.connect();

		GEvent.clearListeners(intersection.marker,'click');
		GEvent.addListener(intersection.marker,'click',this.getWaypointInfoWindowFn(intersection.id));
		this.map.addOverlay(intersection.marker);
	};
	
	RouteBuilder.prototype.getWaypointInfoWindowFn = function( index ) {
		var n_this = this;
		var intersection = n_this.intersections[index];
		return function() {
			GEvent.clearListeners(intersection.marker,'mouseover');
			GEvent.clearListeners(intersection.marker,'mouseout');
			n_this.drawWaypointOverlays(index);
			n_this.getWaypointInfoWindow(index);
		};
	};
	
	RouteBuilder.prototype.drawWaypointOverlaysFn = function( index ) {
		var n_this = this;
		return function() {
			n_this.drawWaypointOverlays(index);
		};
	};
	
	RouteBuilder.prototype.clearWaypointOverlaysFn = function( index ) {
		var n_this = this;
		return function() {
			n_this.clearWaypointOverlays(index);
		};
	};
	
	RouteBuilder.prototype.getWaypointInfoWindow = function( index ) {
		var n_this = this;
		
		var intersection = this.intersections[index];
		var div = intersection.getOptionWindow(this.distance,this.climb,this);
		intersection.marker.openInfoWindow(div);
		
		if ( this.intersections[index].directions.length > 0 || ( this.route.length > 0 && index == this.route[this.route.length-1] ) ) {
			var d_1 = DOMElement('div','');
			var a_0 = DOMElement('a','');
			var a_1 = DOMElement('a','');
			var span = DOMElement('span','header');
			span.appendChild(document.createTextNode('Options'));
			d_1.appendChild(span);
			this.insertLineBreaks(d_1,1);
			a_0.setAttribute('href','javascript:;');
			a_0.appendChild(document.createTextNode('save route'));
			a_1.setAttribute('href','javascript:;');
			a_1.appendChild(document.createTextNode('start over'));
			a_1.onclick = function(){n_this.getNodes();};
			a_0.onclick = function(){n_this.trySaveRoute();};
			d_1.appendChild(document.createTextNode('[ '));
			d_1.appendChild(a_0);
			d_1.appendChild(document.createTextNode(' ] [ '));
			d_1.appendChild(a_1);
			d_1.appendChild(document.createTextNode(' ]'));
			d_1.style.paddingTop = '10px';
			
			div.appendChild(d_1);
		}
		
		GEvent.addListener(this.map.getInfoWindow(),'closeclick',function() {
			n_this.map.closeInfoWindow();
			n_this.clearWaypointOverlays(index);
			GEvent.addListener(intersection.marker,'mouseover',n_this.drawWaypointOverlaysFn(index));
			GEvent.addListener(intersection.marker,'mouseout',n_this.clearWaypointOverlaysFn(index));
		});
	};
	
	RouteBuilder.prototype.drawWaypointOverlays = function( index ) {
		for ( var i = 0; i < this.intersections[index].options.length; ++i )
			this.map.addOverlay(this.intersections[index].options[i].path);
	};
	
	RouteBuilder.prototype.clearWaypointOverlays = function( index ) {
		if ( !this.intersections[index] ) return;
		
		for ( var i = 0; i < this.intersections[index].options.length; ++i )
			this.map.removeOverlay(this.intersections[index].options[i].path);
	};
	
	RouteBuilder.prototype.getMostRecentDirection = function( road ) {
		if ( this.route.length < 3 )
			return this.getInitialHeading(road,this.intersections[this.route[0]]);
			
		return this.getRelativeHeading(road);
	};
	
	RouteBuilder.prototype.getRelativeHeading = function( road ) {
		var intersection = this.intersections[this.route[this.route.length-2]];
		var center = intersection.marker.getPoint();
		var lat = center.lat();
		var lng = center.lng();
		
		var p_road = this.intersections[this.route[this.route.length-3]].directions[this.intersections[this.route[this.route.length-3]].directions.length-1].road;
		var endpoints_0 = p_road.getEndpointsByLatLng(lat,lng);
		var endpoints_1 = road.getEndpointsByLatLng(lat,lng);
		endpoints_0.push(endpoints_1[0]);
		
		return this.getTriangularDirection(endpoints_0)+' onto '+road.name;
	};
	
	RouteBuilder.prototype.getDebugMarker = function( marker, text ) {
		return function() {
			marker.openInfoWindow(document.createTextNode(text));
		};
	};
	
	RouteBuilder.prototype.getTriangularDirection = function( points ) {
		var dx_0 = points[1].lng()-points[0].lng();
		var dx_1 = points[2].lng()-points[1].lng();
		var dy_0 = points[1].lat()-points[0].lat();
		var dy_1 = points[2].lat()-points[1].lat();
		
		var at_0 = Math.atan2(dy_0,dx_0);
		var at_1 = Math.atan2(dy_1,dx_1);
	
		var d_atan = at_1 - at_0;
//		alert(parseInt(at_0*180/Math.PI)+'\n'+parseInt(at_1*180/Math.PI)+'\n\n'+parseInt(d_atan*180/Math.PI));
		while ( d_atan < 0 ) d_atan += 2*Math.PI;
		
		var turn = d_atan > Math.PI ? 'right' : 'left';
		
		var t_str = (1/12)*Math.PI;
		var t_bea = (1/6)*Math.PI;
		var t_tur = (5/6)*Math.PI;
		var t_har = (11/12)*Math.PI;
		
		if ( d_atan > Math.PI ) d_atan = 2*Math.PI-d_atan;
		
		if ( d_atan < t_str ) return 'continue';
		else if ( d_atan < t_bea ) return 'bear '+turn;
		else if ( d_atan < t_tur ) return 'turn '+turn;
		else if ( d_atan < t_har ) return 'hard '+turn;
		
		return 'U-turn';
	};
	
	RouteBuilder.prototype.getInitialHeading = function( road, intersection ) {
		var i0 = this.intersections[this.route[0]];
		var c0 = i0.marker.getPoint();
		var lat = c0.lat();
		var lng = c0.lng();
		
		var endpoints = road.getEndpointsByLatLng(lat,lng);
		//var c = Math.atan2((endpoints[0].lng()-endpoints[1].lng()),(endpoints[0].lat()-endpoints[1].lat()));
		var c = Math.atan2(endpoints[0].lat()-endpoints[1].lat(),endpoints[0].lng()-endpoints[1].lng());
		return 'begin at '+intersection.name+', heading '+this.cardinalDirection(c)+' on '+road.name;
	};
	
	RouteBuilder.prototype.cardinalDirection = function( c ) {		
		var d = c*8/Math.PI;
		
		//alert(Math.round(c*180/Math.PI)+'\n'+Math.round(d));
		if ( d < -7 ) return 'west';
		if ( d < -5 ) return 'southwest';
		if ( d < -3 ) return 'south';
		if ( d < -1 ) return 'southeast';
		if ( d < 1 ) return 'east';
		if ( d < 3 ) return 'northeast';
		if ( d < 5 ) return 'north';
		if ( d < 7 ) return 'northwest';
		return 'west';
	};
	
	RouteBuilder.prototype.makeLatestDirectionRow = function() {
		var n_this = this;
		var tr = DOMElement('tr','');//,'r_'+(this.route.length%2==0?'odd':'even'));
		var directions = this.intersections[this.route[this.route.length-2]].directions;
		var direction = directions[directions.length-1];
		var direction_text = direction.direction.substring(0,1).toUpperCase()+direction.direction.substring(1);
		
		var td_0 = DOMElement('td','mileage');
		var td_1 = DOMElement('td','direction');
		var span = DOMElement('span','');
		var d_0 = DOMElement('div','');
		var d_1 = DOMElement('div','');
		var nobr = DOMElement('nobr','');
		nobr.appendChild(document.createTextNode(round(direction.distance,2)+' mi'));
		d_0.appendChild(nobr);
		td_0.appendChild(d_0);
		span.appendChild(document.createTextNode(direction_text));
		d_1.appendChild(span);
		td_1.appendChild(d_1);
		
		var input = DOMElement('input','');
		input.setAttribute('type','text');
		input.setAttribute('value',direction_text);
		input.style.width = '100%';
		input.style.display = 'none';
		input.style.fontSize = '9pt';
		input.style.borderWidth = '1px';
		input.style.borderStyle = 'solid';
		input.style.padding = '0px';
		input.setAttribute('isfocused','F');
		td_1.appendChild(input);
		td_1.onmouseover = function() {
			span.style.display = 'none';
			input.style.display = 'inline';
			//input.focus();
		};
		var onblur = function() {
			input.style.display = 'none';
			span.removeChild(span.firstChild);
			span.appendChild(document.createTextNode(input.value));
			span.style.display = 'inline';
			input.setAttribute('isfocused','F');
		};
		input.onfocus = function() {
			input.setAttribute('isfocused','T');
		};
		input.onmouseout = function() {
			if ( input.getAttribute('isfocused') != 'T' )
				onblur();
		};
		// subtract 1 for indexing, 1 for the fact that it's the previous node
		var routelen = this.route.length-2;
		input.onchange = function() {
			n_this.setDirection(routelen,input.value);
		};
		tr.onmouseout = input.onmouseout;
		input.onblur = onblur;
		
		tr.appendChild(td_0);
		tr.appendChild(td_1);
		return tr;
	};
	
	RouteBuilder.prototype.setDirection = function( index, direction ) {
		var intersection = this.route[index];
		var count = 0;
		for ( var i = 0; i < index; ++i ) {
			if ( this.route[i] == intersection )
				++count;
		}
		
		this.intersections[intersection].directions[count].direction = direction;
	};
	
	RouteBuilder.prototype.showLoadWindow = function( title, msg ) {
		if ( !title )
			title = 'loading';
		if ( !msg )
			msg = 'Loading intersections';
		var div = DOMElement('div','window_content');
		var span = DOMElement('span','');
		div.style.width = '250px';
		div.appendChild(document.createTextNode(msg));
		span.appendChild(document.createTextNode(''));
		div.appendChild(span);
		//div.appendChild(document.createTextNode(''));
		
		var n_this = this;
		this.is_loading = true;
		
		var date = new Date();
		var close_window = this.manager.makeCloseWindow(this.manager.openWindow(div,title,null),null);
		setTimeout(function(){n_this.loadTimer(span,date,close_window);},100);
	};
	
	RouteBuilder.prototype.stopLoad = function() {
		this.is_loading = false;
	};
	
	RouteBuilder.prototype.loadTimer = function( span, date, close_window ) {
		if ( !this.is_loading ) {
			close_window();
			return;
		}
		
		var n_date = new Date();
		var elapsed = n_date.valueOf() - date.valueOf();
		
		span.removeChild(span.firstChild);
		//span.appendChild(document.createTextNode(round(elapsed/1000,1)));
		var dots = '';
		for ( var i = 0; i < (elapsed/200)%3+1; ++i )
			dots += '.';
		span.appendChild(document.createTextNode(dots));
		
		var n_this = this;
		setTimeout(function(){n_this.loadTimer(span,date,close_window);},100);
	};
	
	RouteBuilder.prototype.clearFromDirection = function( id, direction ) {
		GEvent.trigger(this.map.getInfoWindow(),'closeclick');
//		this.map.closeInfoWindow();
		this.clearTempIntersections();
		
		var i = 0;
		while ( this.route[i] != id || direction > 0 ) {
			if ( this.route[i] == id )
				--direction;
			++i;
		}
		
		var i_0 = i;
		++i;
		for ( i; i < this.route.length; ++i ) {
			if ( this.intersections[this.route[i]] && !this.intersections[this.route[i]].popDirection(this) ) {
				var marker = this.intersections[this.route[i]].marker;
				GEvent.clearInstanceListeners(marker);
				this.map.removeOverlay(marker);
//				alert('clearing\n'+this.intersections[this.route[i]].name);
				this.intersections[this.route[i]] = null;
			}
			
			this.tbody.removeChild(this.tbody.childNodes[this.tbody.childNodes.length-(this.route.length-i)]);
//			this.tbody.removeChild(this.tbody.childNodes[this.tbody.childNodes.length-1]);
		}
		
		while ( this.route.length > i_0 + 1 ) this.route.pop();
		
		this.intersections[this.route[i_0]].popDirection(this);
		this.loadNextNodes(this.intersections[this.route[i_0]]);
	};
	
	RouteBuilder.prototype.decrementAccumulators = function( length, climb ) {
		this.distance -= length;
		this.climb -= climb;
	};
	
	RouteBuilder.prototype.trySaveRoute = function() {
		var n_this = this;
		confirmDialog('Finish editing and save route?','save route',function(){n_this.getRouteInfo();},this.manager);
	};
	
	RouteBuilder.prototype.getRouteInfo = function() {
		var div = DOMElement('div','window_content');
		div.style.width = '220px';
		
		var name_input = DOMElement('input','');
		name_input.setAttribute('type','text');
		this.addFormInput(div,'Route name',name_input,null);

		var is_public = document.createElement('input');
		is_public.setAttribute('id','is_public');
		is_public.setAttribute('name','is_public');
		is_public.setAttribute('type','checkbox');
		is_public.setAttribute('checked','checked');

		var is_public_label = document.createElement('label');
		is_public_label.setAttribute('for','is_public');
		is_public_label.appendChild(document.createTextNode('Make searchable'));

		div.appendChild(is_public);
		div.appendChild(is_public_label);
		this.insertLineBreaks(div,1);
		
		var image_dimensions = new Array();
		image_dimensions.width = 16;
		image_dimensions.height = 16;
		var rating = new ImageLevelSelector('/inc/images/star.gif','/inc/images/nostar.gif',5,0,image_dimensions);
		var difficulty = new ImageLevelSelector('/inc/images/mtn.gif','/inc/images/nomtn.gif',5,0,image_dimensions);
		var table = document.createElement('table');
		var tbody = document.createElement('tbody');
		var tr0 = document.createElement('tr');
		var tr1 = document.createElement('tr');
		var td00 = document.createElement('td');
		var td01 = document.createElement('td');
		var td10 = document.createElement('td');
		var td11 = document.createElement('td');
		td00.appendChild(document.createTextNode('Rating'));
		td01.appendChild(document.createTextNode('Difficulty'));
		td10.appendChild(rating.makeSelector());
		td10.style.paddingRight = '20px';
		td11.appendChild(difficulty.makeSelector());
		tr0.appendChild(td00);
		tr0.appendChild(td01);
		tr1.appendChild(td10);
		tr1.appendChild(td11);
		tbody.appendChild(tr0);
		tbody.appendChild(tr1);
		table.appendChild(tbody);
		div.appendChild(table);
		this.insertLineBreaks(div,1);
		
		var flags = new FlagSelector();
		this.addFormInput(div,'Flags',flags.makeSelector(),null);
		
//		this.insertLineBreaks(div,1);
		var comments = document.createElement('textarea');
		comments.style.width = '200px';
		comments.setAttribute('id','comments');
		this.addFormInput(div,'Comments',comments,null);
		
		var ok_button = makeButton('save');
		var cancel_button = makeButton('cancel');
		var center = document.createElement('center');
		center.appendChild(ok_button);
		center.appendChild(cancel_button);
		div.appendChild(center);
		
		var close_window = this.manager.makeCloseWindow(this.manager.openWindow(div,'save road',null),null);
		cancel_button.onclick = function() {close_window();};
		var n_this = this;
		ok_button.onclick = function() {
			// do something important!
			var post_data = {
				name: name_input.value,
				rating: rating.getSelectedLevel(),
				difficulty: difficulty.getSelectedLevel(),
				flags: flags.getFlags(),
				comments: comments.value,
				is_public: is_public.checked ? 1 : 0
			};
			//var post_data = new Array();
			
			//post_data.name = name_input.value;
			//post_data.rating = rating.getSelectedLevel();
			//post_data.difficulty = difficulty.getSelectedLevel();
			//post_data.flags = flags.getFlags();
			//post_data.comments = comments.value;
			
			// need to pass all the data...
			n_this.saveRoute(post_data,close_window);
		};
		
		name_input.focus();
	};
	
	RouteBuilder.prototype.saveRoute = function( post_data, close_window ) {
		this.showLoadWindow('saving','Saving route');
		
		var ajax_url = '/include/xml/route.add.php';
		var post_str = '';
		
		for ( var k in post_data ) post_str += k + '=' + encodeURIComponent(post_data[k]) + '&';
		var d_count = new Array();
		for ( var i in this.intersections ) d_count[i] = 0;
		for ( var i = 0; i < this.route.length; ++i ) {
			var intersection = this.intersections[this.route[i]];
			var direction = intersection.directions[d_count[intersection.id]++];
			
			post_str += 'i'+i+'='+intersection.id+'&';
			if ( direction ) {
				post_str += 'r'+i+'='+direction.road.id+'&';
				post_str += 'd'+i+'='+encodeURIComponent(direction.direction.substring(0,1).toUpperCase()+direction.direction.substring(1))+'&';
			}
		}
		
		var n_this = this;
		var success_fn = function( responseXML, responseText ) {
			// do something about logging in at some point...
			n_this.map.clearOverlays();
			n_this.stopLoad();
			
			// get the routeID
			var stati = responseXML.getElementsByTagName('status');
			if ( stati[0].getAttribute('success') == 'T' ) {
				close_window();
				parent.location = 'route.view.php?routeid='+stati[0].getAttribute('routeid');
			} else
				n_this.forceLogin();
		};
		// -1) general data
		// 0) region?
		// 1) start node
		// 2) via road
		// 3) direction
		// the db can handle the rest via JOINs
		
		var ajax_request = new ajax(ajax_url,success_fn,null,post_str);
		ajax_request.connect();
	};
	
	RouteBuilder.prototype.addFormInput = function( form, text, input, suffix ) {
		form.appendChild(document.createTextNode(text));
		this.insertLineBreaks(form,1);
		form.appendChild(input);
		if ( suffix )
			form.appendChild(document.createTextNode(suffix));
		this.insertLineBreaks(form,1);
	};
	
	RouteBuilder.prototype.forceLogin = function() {
		new LoginWindow(this.manager).showLoginWindow(false);
	};

	RouteBuilder.prototype.showRoadInfo = function( road_id, intersection_id ) {
		var div = DOMElement('div','window_content');
		div.style.width = '300px';
		div.style.height = '250px';

		var iframe = DOMElement('iframe','');
		iframe.setAttribute('src','/road.view.php?roadid='+road_id+'&intersectionid='+intersection_id);
		iframe.style.width = '296px';
		iframe.style.height = '246px';
		iframe.style.border = '1px';
		div.appendChild(iframe);

		var close_window = this.manager.makeCloseWindow(this.manager.openWindow(div,'road info',null),null);
	};
}

