
// contains bulk of propegation code
// both the propegation google earth overlay object, and the
// tower object that contains variables



// form input control template
function makeInput(name, title, value, units, size) {
	if(units == "readonly") {
		//return "<label for='"+name+"'>"+title+":</label><input id='"+name+"' value='"+value+"' size='"+size+"' style='border:0px none;' /> &nbsp;&nbsp;";
	} else {
		return "<label for='"+name+"'>"+title+":</label><input id='"+name+"' value='"+value+"' size='"+size+"' onKeyPress='towerkey(event)' /> "+units+"&nbsp;&nbsp;";
	}
}


function htmlcolor(r, g, b) {
	var color = b + 256 * g + 65536 * r;
	color = color.toString(16);
	for(i=color.length; i<6; i++)
		color = "0"+color;
	return color;
}

// pack a tower description for url transportation
function packTower(tower) {
	return tower.marker_.getPoint().lat()+","+tower.marker_.getPoint().lng()+","+
		tower.prop_.bounds_.getSouthWest().lat()+","+tower.prop_.bounds_.getSouthWest().lng()+","+
		tower.prop_.bounds_.getNorthEast().lat()+","+tower.prop_.bounds_.getNorthEast().lng()+","+
		tower.detail_+","+tower.r_+","+tower.g_+","+tower.b_+","+tower.txheight_+","+tower.rxheight_+","+
		tower.eirp_+","+tower.freq_+","+tower.txantenna_+","+tower.rxantenna_+","+tower.sens_+","+
		tower.title_+","+tower.icon_;
}

function packHistory(tower) {
	var out = "";
	for(i in tower.history_) {
		var point = tower.history_[i];
		out += point[0]+"|"+point[1].lat()+"|"+point[1].lng()+";";
	}
	return out;
}



// ------------------------------------------------- ICONSET --------

function Iconset(tower, root, defcolor, deficon) {
	var div = document.createElement("div");
	var iconlist = [];
	
	this.tower_ = tower;
	this.color_ = defcolor;
	this.icon_ = undefined;
	
	var is = this;
	
	// dump the icon interface at the node given
	var label = document.createElement("label");
	label.innerHTML = "Icon:";
	div.appendChild(label);
	
	for(i in icons) {
		var icon = document.createElement("img");
		icon.src = icons[i];
		icon.align = "absmiddle";
		if(deficon.indexOf(icons[i]) >= 0) {
			icon.style.background = "silver";
			this.icon_ = icon;
		}
		div.appendChild(icon);
		iconlist.push(icon);
		
		icon.onclick = function(e) {
			for(i in iconlist) {
				var icon = iconlist[i];
				icon.style.background = (icon == e.target) ? "silver" : "none";
				is.icon_ = e.target;
			}
			is.tower_.updateiconset(is.color_, is.icon_.src);
		}
	}
	
	// dump out list of all colors available
	div.appendChild(document.createElement("br"));
	var label = document.createElement("label");
	label.innerHTML = "Color:";
	div.appendChild(label);
	
	var select = document.createElement("select");
	select.style.margin = "3px 0px 0px 0px";
	div.appendChild(select);
	for(c in colors) {
		var option = document.createElement("option");
		option.value = colors[c][1];
		option.innerHTML = colors[c][0];
		if(option.value == this.color_)
			option.selected = true;
		select.appendChild(option);
	}
	
	select.onchange = function() {
		// recolor the current iconset
		is.color_ = select.value;
		var color = select.value.split(",");
		for(i in iconlist) {
			var icon = iconlist[i];
			icon.src = "hue.php?image="+icons[i]+"&r="+color[0]+"&g="+color[1]+"&b="+color[2];
		}
		is.tower_.updateiconset(is.color_, is.icon_.src);
	}
	
	select.onchange();
	root.appendChild(div);
}



// ------------------------------------------------- PROPEGATION --------

var NONE = 0;
var TOPLEFT = 1;
var TOPRIGHT = 2;
var BOTTOMLEFT = 3;
var BOTTOMRIGHT = 4;
var EQUAL = 5;

var kmlat = 0.0090175;
var kmlon = 0.0120425;

function parseSize(size) {
	return parseInt(size.replace("px",""));
}

function Propegation(tower, southwest, northeast) {

	this.weight_ = 0;
	this.color_ = "#ffffff";

	this.resizedir_ = NONE;
	this.resizing_ = false;
	
	var center = tower.marker_.getPoint();
	this.tower_ = tower;
	this.lastcenter_ = center;
	
	//if(undefined == southwest || undefined == northeast) {
	if(southwest.lat() == -1) {
		this.bounds_ = new GLatLngBounds(
			new GLatLng(center.lat() - (kmlat*1), center.lng() - (kmlon*1)),
			new GLatLng(center.lat() + (kmlat*1), center.lng() + (kmlon*1)));
	} else {
		this.bounds_ = new GLatLngBounds(southwest, northeast);
	}
	
	this.clear = function() {
		this.img_.src = "tpx.gif";
	}
	
	this.busy = function() {
		this.img_.src = "bigrotation2.gif";
	}
	
	this.visible = true;
	this.toggle = function() {
		this.setvisible(!this.visible);
	}
	this.setvisible = function(newvisible) {
		this.visible = newvisible;
		this.div_.style.display = (this.visible) ? "" : "none";
		// just to be sure, refresh image when turned back on
		if(newvisible)
			this.generate(tower);
	}
	
	this.resize = false;
	this.setresize = function(newresize) {
		this.resize = newresize;
		this.resize_.style.display = (this.resize) ? "" : "none";
	}
	
	this.move = function(tower) {
		// move this object under the center point given
		// todo: rewrite to set correct bounds if odd resize
		var center = tower.marker_.getLatLng();
		var x = center.lng() - this.lastcenter_.lng();
		var y = center.lat() - this.lastcenter_.lat();
		
		var southwest = this.bounds_.getSouthWest();
		var northeast = this.bounds_.getNorthEast();
		
		this.bounds_ = new GLatLngBounds(
			new GLatLng(southwest.lat() + y, southwest.lng() + x),
			new GLatLng(northeast.lat() + y, northeast.lng() + x));
		
		this.lastcenter_ = center;
	}
	
	this.generate = function(tower) {
		// only calculate if visible
		if(!this.visible) {
			this.redraw(true);
			return;
		}
		
		// pull new propegation image
		this.busy();
		
		// convert detail in meters to pixels based on bounds
		var tower = this.tower_;
		
		var img = this.img_;
		var url = "plot.cgi?"+packTower(tower);
		
		var image = new Image();
		image.onload = function() {
			img.src = url;
		}
		image.src = url;
		
		this.redraw(true);
	}

}

Propegation.prototype = new GOverlay();


Propegation.prototype.initialize = function(map) {
	
	var prop = this;
	
	var div = document.createElement("div");
	div.style.position = "absolute";
	
	
	var img = document.createElement("img");
	img.src = "tpx.gif";
	img.style.width = "100%";
	img.style.height = "100%";
	div.appendChild(img);
	
	var resize = document.createElement("img");
	resize.src = "resize.png";
	resize.style.position = "absolute";
	resize.style.top = "0px";
	resize.style.left = "0px";
	resize.style.width = "100%";
	resize.style.height = "100%";
	resize.style.opacity = 0.5;
	resize.style.display = "none";
	div.appendChild(resize);
	
	
	GEvent.addListener(map, "mousemove", function(point) {
		
		
		
		// handle resizing if needed
		if(prop.resizing_) {
			var SouthWest = prop.bounds_.getSouthWest();
			var NorthEast = prop.bounds_.getNorthEast();
			if(prop.resizedir_ == EQUAL) {
				if(point.lng() < SouthWest.lng()) return false;
				// any change on east edge is spread uniformly in all directions
				var londist = point.lng() - NorthEast.lng();
				var latdist = (londist / kmlon) * kmlat;
				prop.bounds_ = new GLatLngBounds(new GLatLng(SouthWest.lat() - latdist, SouthWest.lng() - londist),
					new GLatLng(NorthEast.lat() + latdist, NorthEast.lng() + londist));
				prop.redraw(true);
			} else if(prop.resizedir_ == TOPRIGHT) {
				if((point.lat() < SouthWest.lat()) || (point.lng() < SouthWest.lng())) return false;
				prop.bounds_ = new GLatLngBounds(SouthWest, point);
				prop.redraw(true);
			} else if(prop.resizedir_ == BOTTOMLEFT) {
				if((point.lat() > NorthEast.lat()) || (point.lng() > NorthEast.lng())) return false;
				prop.bounds_ = new GLatLngBounds(point, NorthEast);
				prop.redraw(true);
			} else if(prop.resizedir_ == TOPLEFT) {
				if((point.lat() < SouthWest.lat()) || (point.lng() > NorthEast.lng())) return false;
				prop.bounds_ = new GLatLngBounds(new GLatLng(SouthWest.lat(), point.lng()),
					new GLatLng(point.lat(), NorthEast.lng()));
				prop.redraw(true);
			} else if(prop.resizedir_ == BOTTOMRIGHT) {
				if((point.lng() > NorthEast.lat()) || (point.lng() < SouthWest.lng())) return false;
				prop.bounds_ = new GLatLngBounds(new GLatLng(point.lat(), SouthWest.lng()),
					new GLatLng(NorthEast.lat(), point.lng()));
				prop.redraw(true);
			}
		} else {
			
			// figure out if movement is inside this block
			var SouthWest = prop.bounds_.getSouthWest();
			var NorthEast = prop.bounds_.getNorthEast();
			
			prop.resizedir_ = NONE;
			if(!prop.resize) return false;
			
			if(point.lat() > SouthWest.lat() && point.lat() < NorthEast.lat() &&
				point.lng() > SouthWest.lng() && point.lng() < NorthEast.lng()) {
				
				// figure out fractional range inside image
				var x = (point.lng() - NorthEast.lng()) / (SouthWest.lng() - NorthEast.lng());
				var y = (point.lat() - SouthWest.lat()) / (NorthEast.lat() - SouthWest.lat());
				
				if(x < 0.1 && y > 0.4 && y < 0.6) prop.resizedir_ = EQUAL;
				if(x < 0.1 && y < 0.1) prop.resizedir_ = BOTTOMRIGHT;
				if(x < 0.1 && y > 0.9) prop.resizedir_ = TOPRIGHT;
				if(x > 0.9 && y < 0.1) prop.resizedir_ = BOTTOMLEFT;
				if(x > 0.9 && y > 0.9) prop.resizedir_ = TOPLEFT;
			}
			resize.style.opacity = (prop.resizedir_ == NONE) ? 0.5 : 1.0;
			
		}
		
		return false;
	});
	
	
	GEvent.addListener(map, "click", function(overlay, point) {
		if(undefined == point) return;
		if(prop.resizing_) {
			prop.resizing_ = false;
			prop.generate();
		} else if(prop.resizedir_ != NONE) {
			prop.resizing_ = true;
			prop.clear();
		} else {
			prop.setresize(false);
		}
	
		return false;
	
	});
	
	
	
	
	
	resize.onmouseout = function() {
		if(this.resizing_ == false)
			resize.style.display = "none";
	}
	
	
	
	this.div_ = div;
	this.img_ = img;
	this.resize_ = resize;
	
	map.getPane(G_MAP_MAP_PANE).appendChild(div);
	this.map_ = map;
	
}


Propegation.prototype.remove = function() {
	this.div_.parentNode.removeChild(this.div_);
}


Propegation.prototype.copy = function() {
	return null;
}


Propegation.prototype.redraw = function(force) {
	if(!force) return;

	var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
	var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());

	this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
	this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
	this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
	this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
}









// ------------------------------------------------- TOWER --------



function Tower(map, settings) {
	// towerlat,towerlon,southlat,westlon,northlat,eastlon,detail,
	// 0        1        2        3       4        5       6      
	
	// r,g,b,txheight,rxheight,eirp,freq,txantenna,rxantenna,sens,title,icon,
	// 7 8 9 10       11       12   13   14        15        16   17    18   
	
	// history,speed
	// 19      20
	
	var settings = settings.split(",");
	
	var center = new GLatLng(parseFloat(settings[0]), parseFloat(settings[1]));
	var southwest = new GLatLng(parseFloat(settings[2]), parseFloat(settings[3]));
	var northeast = new GLatLng(parseFloat(settings[4]), parseFloat(settings[5]));
	
	this.detail_ = parseInt(settings[6]);
	
	this.r_ = parseInt(settings[7]);
	this.g_ = parseInt(settings[8]);
	this.b_ = parseInt(settings[9]);
	
	this.txheight_ = parseFloat(settings[10]);
	this.rxheight_ = parseFloat(settings[11]);
	this.eirp_ = parseFloat(settings[12]);
	this.freq_ = parseFloat(settings[13]);
	this.txantenna_ = parseFloat(settings[14]);
	this.rxantenna_ = parseFloat(settings[15]);
	this.sens_ = parseFloat(settings[16]);
	
	this.title_ = settings[17];
	this.icon_ = settings[18];
	
	var tower = this;
	
	var icon = new GIcon();
	if(this.icon_.indexOf("hue.php") == -1) {
		icon.image = "hue.php?image="+this.icon_+"&r="+this.r_+"&g="+this.g_+"&b="+this.b_;
	} else {
		icon.image = this.icon_;
	}
	icon.iconSize = new GSize(32,32); //G_DEFAULT_ICON.iconSize;
	icon.iconAnchor = new GPoint(16,24); //G_DEFAULT_ICON.iconAnchor;
	icon.infoWindowAnchor = new GPoint(32,0); //G_DEFAULT_ICON.infoWindowAnchor;
	icon.maxHeight = 24;
	
	var marker = new GMarker(center, {draggable:true, icon:icon, bouncy:false, autoPan:true, dragCrossMove:true});
	this.marker_ = marker;
	var prop = new Propegation(this, southwest, northeast);
	
	GEvent.addListener(marker, "dragstart", function() {
		// hide current prop study and any open windows
		prop.clear();
		map.closeInfoWindow();
	});
	
	GEvent.addListener(marker, "dragend", function() {
		// move rectangle
		prop.move(tower);
		prop.generate(tower);
		
		forcetop(tower);
		
		// update history path temporarily
		tower.history_.push([-1,tower.marker_.getPoint()]);
		tower.updatesnapshot();
		tower.history_.pop();
		
	});
	
	GEvent.addListener(marker, "click", function() {
		// bring this overlay to top
		forcetop(tower);
		
		id = 0;
		active = tower;
		
		var tabs = [];
		tabs.push(new GInfoWindowTab("General", "<table class='tower'><tr><td colspan=2>"+
			makeInput("title"+id, "Title", tower.title_, "", 30)+"<br>"+
			makeInput("location"+id, "Location", tower.marker_.getLatLng().lat().toFixed(6)+","+tower.marker_.getLatLng().lng().toFixed(6), "", 30)+
			"</td></tr><tr><td>"+
			"<div id='iconset"+id+"'></div>"+
			"</td></tr></table>"+
			"<input type='button' class='towersave' onclick='active.update()' value='Save' />"));
		tabs.push(new GInfoWindowTab("Radios", "<table class='tower'><tr><td>"+
			makeInput("txheight"+id, "Tx Height", tower.txheight_, "m", 4)+"<br>"+
			makeInput("txantenna"+id, "Tx Antenna", tower.txantenna_, "dBi", 6)+"<br>"+
			makeInput("eirp"+id, "Tx Power", tower.eirp_, "mW", 6)+"<br>"+
			makeInput("freq"+id, "Frequency", tower.freq_, "MHz", 6)+
			"</td><td>"+
			makeInput("rxheight"+id, "Rx Height", tower.rxheight_, "m", 4)+"<br>"+
			makeInput("rxantenna"+id, "Rx Antenna", tower.rxantenna_, "dBi", 6)+"<br>"+
			makeInput("sens"+id, "Sensitivity", tower.sens_, "dB", 6)+
			"</td></tr></table>"+
			"<input type='button' class='towersave' onclick='active.update()' value='Save' />"));
		tabs.push(new GInfoWindowTab("Plot", "<table class='tower'><tr><td>"+
			makeInput("detail"+id, "Resolution", tower.detail_, "m", 4)+
			"<br><label for='display0'>Show Plot:</label><input type='checkbox' style='margin-top:0.5em; margin-bottom:0.1em;' id='display0' onchange='active.prop_.toggle()' "+((tower.prop_.visible) ? "checked" : "")+" />"+
			"</td></tr><tr><td>"+
			"<input type='button' value='Delete Node' onclick='deletetower(active)' />"+
			"</td></tr></table>"+
			"<input type='button' class='towersave' onclick='active.update()' value='Save' />"));
		
		marker.openInfoWindowTabsHtml(tabs);
		var div = document.getElementById("iconset"+id);
		var iconset = new Iconset(tower, div, tower.r_+","+tower.g_+","+tower.b_, tower.icon_);
	});
	
	
	this.map_ = map;
	this.prop_ = prop;

	prop.move(tower);

	map.addOverlay(marker);
	map.addOverlay(prop);

	prop.generate(tower);
	
	this.remove = function() {
		map.removeOverlay(marker);
		map.removeOverlay(prop);
		if(undefined != this.historypoly_)
			map.removeOverlay(this.historypoly_);
	}
	
	this.serialize = function() {
		// dump out string representation of this tower
		
	}
	
	this.packcolor = function() {
		return this.r_+","+this.g_+","+this.b_;
	}
	
	this.updateiconset = function(color, icon) {
		// handle partial updates from iconset
		if(undefined == color || undefined == icon) return;
		
		// only replot if color actually changed
		if(this.packcolor() != color) {
			color = color.split(",");
			this.r_ = parseInt(color[0]);
			this.g_ = parseInt(color[1]);
			this.b_ = parseInt(color[2]);
			
			prop.generate(tower);
			this.updatesnapshot();
		}
		
		this.icon_ = icon;
		tower.marker_.setImage(icon);
	}
	
	this.update = function() {
		// pull in values from box and regen plot if needed
		var id = 0; //tower.number_;

		this.title_ = document.getElementById("title"+id).value;

		this.txheight_ = document.getElementById("txheight"+id).value;
		this.txantenna_ = document.getElementById("txantenna"+id).value;
		this.eirp_ = document.getElementById("eirp"+id).value;
		this.freq_ = document.getElementById("freq"+id).value;

		this.rxheight_ = document.getElementById("rxheight"+id).value;
		this.rxantenna_ = document.getElementById("rxantenna"+id).value;
		this.sens_ = document.getElementById("sens"+id).value;

		this.detail_ = document.getElementById("detail"+id).value;

		// parse in the new lat/lon
		var point = document.getElementById("location"+id).value.split(",");
		var lat = parseFloat(point[0]);
		var lon = parseFloat(point[1]);
		point = new GLatLng(lat, lon);

		if(point.distanceFrom(marker.getPoint()) > 1) {
			map.closeInfoWindow();
			marker.setPoint(point);
			prop.move(tower);
			prop.generate(tower);
			map.setCenter(point);
		}

		prop.clear();
		prop.move(tower);
		prop.generate(tower);

	}
	
	this.history_ = [];
	this.historypoly_ = undefined;
	
	this.snapshot = function(time) {
		// save current location in snapshot list
		// also add to history polyline
		this.history_.push([time,this.marker_.getPoint()]);
		this.updatesnapshot();
	}
	
	this.updatesnapshot = function() {
		if(undefined != this.historypoly_)
			map.removeOverlay(this.historypoly_);
		var points = [];
		for(i in this.history_) {
			points.push(this.history_[i][1]);
		}
		this.historypoly_ = new GPolyline(points, htmlcolor(this.r_, this.g_, this.b_), 5, 0.5);
		map.addOverlay(this.historypoly_);
	}
	
	// handle unpacking history if passed in settings
	if(settings.length > 19) {
		var list = settings[19].split(";");
		for(i in list) {
			var point = list[i].split("|");
			if(point.length != 3) continue;
			var time = parseInt(point[0]);
			var place = new GLatLng(parseFloat(point[1]), parseFloat(point[2]));
			this.history_.push([time,place]);
		}
		this.updatesnapshot();
	}
	
	this.speed_ = -1;
	if(settings.length > 20) {
		this.speed_ = parseFloat(settings[20]);
	}

}


// ------------------------------------------------- INERT --------


function Inert(map, settings) {
	
	var settings = settings.split(",");
	
	this.center_ = new GLatLng(parseFloat(settings[0]), parseFloat(settings[1]));
	this.title_ = settings[2];
	
	var tower = this;
	
	var icon = new GIcon();
	icon.image = "https://sgserv.coe.montana.edu/design/inert.png";
	icon.iconSize = G_DEFAULT_ICON.iconSize;
	icon.iconAnchor = G_DEFAULT_ICON.iconAnchor;
	icon.infoWindowAnchor = G_DEFAULT_ICON.infoWindowAnchor;
	
	var marker = new GMarker(this.center_, {draggable:false, icon:icon, bouncy:false, autoPan:true});
	
	GEvent.addListener(marker, "click", function() {
		var span = document.createElement("span");
		span.className = "tower";
		
		var h3 = document.createElement("h3");
		h3.innerHTML = tower.title_;
		span.appendChild(h3);
		span.appendChild(document.createElement("p"));
		
		var input = document.createElement("input");
		input.type = "button";
		input.value = "Create Tower";
		input.onclick = function() {
			deleteinert(tower);
			opendialog(new CreateDialog(document.body, tower.center_.lat(), tower.center_.lng(), tower.title_));
		}
		span.appendChild(input);
		
		marker.openInfoWindow(span);
	});
	
	this.map_ = map;
	this.marker_ = marker;
	
	map.addOverlay(marker);
	
	this.remove = function() {
		map.removeOverlay(marker);
	}
	
}



