var stdHeight = 165;
var currentAspect = "1.33";
var imgPathPrefix = "cgi-bin/tv.cgi?i=";
var req; // XMLHttpRequest object
var temp;

var numTVs = 2;

var tvw = new Array();
var tvh = new Array();
tvw[1] = Math.round(stdHeight * 1.33);
tvw[2] = Math.round(stdHeight * 1.33);
tvh[1] = stdHeight;
tvh[2] = stdHeight;

var imgw = new Array();
var imgh = new Array();
imgw[1] = tvw[1];
imgh[1] = tvh[1];
imgw[2] = tvw[2];
imgh[2] = tvh[2];

function loadSettings(){
	var q = document.location.search;
	q = q.substr(1, q.length);
	if(q){
		temp = gbi('link').innerHTML;
		gbi('link').innerHTML = "Loading...";
		getString(q);
	}
}

function getString(q){
	req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
	req.open("POST", "http://" + document.location.host + "/cgi-bin/getsettings.cgi", true);
	req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	req.onreadystatechange = loadXML;
	req.send("s=" + q);
}

function loadXML(){
	if(req.readyState == 4 && req.status == 200){
		var string = req.responseXML.documentElement.firstChild.nodeValue;
		var string 
		set(string);
	}
	else if(req.readyState == 4){
		alert("Sorry, there was an error loading this configuration.");
	}
}

function set(string){
	var nums = string.split(',');
	
	var t = gbi("setnumtvsselect");
	for(var ii = 0; ii < t.options.length; ii++){
		if(t.options[ii].value == nums[0]){
			t.selectedIndex = ii;
		}
	}
	
	setNumTVs(nums[0]);
	for(var i = 1; i <= numTVs; i++){
		gbi("tv" + i + "size").value = nums[((i - 1) * 4) + 1];
		
		var ti = nums[((i - 1) * 4) + 2];		
		var s = gbi("tv" + i + "aspect");
		for(var ii = 0; ii < s.options.length; ii++){
			if(s.options[ii].value == ti){
				s.selectedIndex = ii;
			}
		}
		
		gbi("tv" + i + "width").value = nums[((i - 1) * 4) + 3];
		gbi("tv" + i + "height").value = nums[((i - 1) * 4) + 4];
	}
	iaset(nums[nums.length - 1]);
	sizetvs();
	gbi('link').innerHTML = temp;
	
	var hash = document.location.search;
	var url = "http://tvcalculator.com/index.html" + hash;
	gbi("permURL").innerHTML = "Permanent URL: <a href='" + url + "'>" + url + "</a>";
}

function permlink(){
    var savestring = "";
    savestring += numTVs + ",";
	for(var i = 1; i <= numTVs; i++){
		savestring += gbi("tv" + i + "size").value + ",";
		savestring += gbi("tv" + i + "aspect")[gbi("tv" + i + "aspect").selectedIndex].value + ",";	
		savestring += gbi("tv" + i + "width").value + ",";
		savestring += gbi("tv" + i + "height").value + ",";
	}
	savestring += currentAspect;
	gbi("permURL").innerHTML = "Saving...";
	save(savestring);
}

function save(str){
	req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
	req.open("POST", "http://" + document.location.host + "/cgi-bin/savesettings.cgi", true);
	req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
	req.onreadystatechange = showURL;
	req.send("s=" + str);
}

function showURL(){
	if(req.readyState == 4 && req.status == 200){
		var hash = req.responseXML.documentElement.firstChild.nodeValue;
		var url = "http://tvcalculator.com/index.html?" + hash;
		gbi("permURL").innerHTML = "Permanent URL: <a href='" + url + "'>" + url + "</a>";
	}
	else if(req.readyState == 4){
		gbi("permURL").innerHTML = "";
		alert("There was an error saving this configuration. Please try again.");
	}
}

function setNumTVs(n){
	var newNumTVs;
	if(n)
		newNumTVs = n;
	else
		newNumTVs = gbi("setnumtvsselect")[gbi("setnumtvsselect").selectedIndex].value;
    if(newNumTVs > numTVs){
        for(var i = numTVs; i < newNumTVs; i++){
            addTV();
            numTVs++;
        }
        initStatUpdate();
    }
    if(newNumTVs < numTVs){
        for(var i = numTVs; i > newNumTVs; i--){
            removeTV();
            numTVs--;
        }
    }
    sizetvs();
}


function addTV(){
	gbi("permURL").innerHTML = "";
    var tv = numTVs + 1;
    
    var disp = document.createElement("div");
    disp.id = "tv" + tv + "frame";
    disp.className = "tvframe";
	var dispcontent = "<div id='tv" + tv + "' class='tv'><img id='tv" + tv + "img' src='cgi-bin/tv.cgi?i=1.33w100' alt=''/></div>";
    disp.innerHTML = dispcontent;
    var lastTVd = gbi("tv" + numTVs + "frame");
    lastTVd.parentNode.insertBefore(disp, lastTVd.nextSibling);
    
    var info = document.createElement("div");
    info.id = "tv" + tv + "info";
    info.className = "tvinfo";
    
    var infocontent = " \
        <div class='title'>TV " + tv + "</div> \
        <div> \
            <input type='text' id='tv" + tv + "size' value='19' onchange='sizetvs()' /> inches<br /> \
            <select id='tv" + tv + "aspect' onchange='sizetvs()'> \
                <option value='1.25'>5:4</option><option value='1.33' selected='selected'>4:3</option> \
                <option value='1.6'>16:10</option><option value='1.78'>16:9</option> \
            </select> aspect ratio \
            <br /><input type='text' id='tv" + tv + "width' value='1024' /> pixels wide \
            <br /><input type='text' id='tv" + tv + "height' value='768' /> pixels high \
        </div><div id='tv" + tv + "stats' class='tvstats'></div> \
    ";

    info.innerHTML = infocontent;
    var lastTV = gbi("tv" + numTVs + "info");
    lastTV.parentNode.insertBefore(info, lastTV.nextSibling);
}

function removeTV(){
	gbi("permURL").innerHTML = "";
    var display = gbi("tv" + numTVs + "frame");
    display.parentNode.removeChild(display);
    var display = gbi("tv" + numTVs + "info");
    display.parentNode.removeChild(display);
}

function init(){
    gbi("1.33").onclick = function(){iaset("1.33")}
    gbi("1.78").onclick = function(){iaset("1.78")}
    gbi("1.85").onclick = function(){iaset("1.85")}
    gbi("2.35").onclick = function(){iaset("2.35")}
    gbi("0").onclick = function(){iaset("0")}
    initStatUpdate();
    sizetvs();
    iaset("1.33");
	loadSettings();
}

function initStatUpdate(){
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        gbi("tv" + tv + "width").onkeyup = tvstats;
        gbi("tv" + tv + "height").onkeyup = tvstats;
        gbi("tv" + tv + "width").onchange = tvstats;
        gbi("tv" + tv + "height").onchange = tvstats;
    }
}

function iaset(elName){
    gbi("1.33").className = "off";
    gbi("1.78").className = "off";
    gbi("1.85").className = "off";
    gbi("2.35").className = "off";
    gbi("0").className = "off";
    gbi(elName).className = "on";
    currentAspect = gbi(elName).id;
    draw();
}

function draw(){
    gbi("permURL").innerHTML = "";
    // Iterate across each tv
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        
        var tvsrc = imgPathPrefix + currentAspect;
        var tvaspect = gbi("tv" + tv + "aspect")[gbi("tv" + tv + "aspect").selectedIndex].value;
        if(currentAspect <= tvaspect){ // The image is narrower than (or equal to) the TV.
            imgh[tv] = tvh[tv];
            imgw[tv] = Math.round(tvh[tv] * currentAspect);
            tvsrc += "h" + tvh[tv];
        }
        else{ // The image is wider than the TV
            imgh[tv] = Math.round(tvh[tv] * tvaspect / currentAspect);
            imgw[tv] = tvw[tv];
            tvsrc += "w" + tvw[tv];
        }
        // Set the values.
        gbi("tv" + tv + "img").style.height = imgh[tv] + "px";
        gbi("tv" + tv + "img").style.width = imgw[tv] + "px";
        gbi("tv" + tv).style.height = tvh[tv] + "px";
        gbi("tv" + tv).style.width = tvw[tv] + "px";
        gbi("tv" + tv + "img").src = tvsrc;
        // Center the image vertically on the TV.
        gbi("tv" + tv + "img").style.marginTop = Math.floor((tvh[tv] - imgh[tv]) / 2) + "px";
        
    }
    
    // Then we make the baselines of all TVs align.
    tallestTV = 0;
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        if(tvh[tv] > tallestTV) tallestTV = tvh[tv];
    }
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        gbi("tv" + tv + "frame").style.marginTop = (tallestTV - tvh[tv]) + "px";
    }
    
    // Then we draw statistical info below the tvs.
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        tvstats(tv);
    }
}

// There are up to 9 TVs allowed before this breaks. Fewer will likely fit on
// an average display.
// e is either an event, or the number of the TV. If it's an event, the TV
// number should be the third character of the id of the event's source HTML
// element.
function tvstats(e){
    var tvnum = 0;
    if (!e) e = window.event; // This holds either an int, or an event.
    
    if(e > 0 && e < 8){ // if it's an int, do this.
        tvnum = e;
    }
    else{ // otherwise, must be an event.
        var target;
        if (e.target) target = e.target;
        else if (e.srcElement) target = e.srcElement;
        tvnum = Number(target.id.substr(2,1));
    }
    
    var tvstat = "";
    var tva = gbi("tv" + tvnum + "aspect")[gbi("tv" + tvnum + "aspect").selectedIndex].value;
    var tvs = gbi("tv" + tvnum + "size").value;
    var w = Math.round((tvs * ( tva / Math.sqrt(tva * tva + 1))) * 100) / 100;
    var h = Math.round((tvs / Math.sqrt(tva * tva + 1)) * 100) / 100;
    var tvArea = Math.round((w * h) * 100) / 100;
    var vw = w;
    var vh = h;
    tvstat += "<b>Viewable Image Info:</b><br/>";
    tvstat += "Image Dimensions: ";
    if(currentAspect == 0){
        tvstat += w + "\" x " + h + "\"<br/>Image area: " + tvArea + " sq. in.";
    }
    else{
        if(currentAspect > tva){vh = Math.round((h * (tva / currentAspect)) * 100) / 100;}
        else{vw = Math.round((h * currentAspect) * 100) / 100;}
        var imageArea = Math.round((vw * vh) * 100) / 100;
        var util = Math.round((imageArea / tvArea) * 10000) / 100;
        if(util > 100){util = 100;}
        tvstat += vw + "\" x " + vh + "\"<br/>Image area: " + imageArea + " sq. in.";
        tvstat += "<br/>Screen Utilization: " + util + "%";
    }
    
    tvstat += "<br/><br/><b>General TV Info:</b>";
    
    // Equivelent sizes
    if(tva >  1.33){
        var eqw = h * 1.33;
        var equiv = Math.round(Math.sqrt(h * h + eqw * eqw) * 10) / 10;
        tvstat += "<br/>Equivalent 4:3 TV: " + equiv + "\"";
    }
     if(tva <  1.33){
        var eqh = w / 1.33;
        var equiv = Math.round(Math.sqrt(w * w + eqh * eqh) * 10) / 10;
        tvstat += "<br/>Equivalent 4:3 TV: " + equiv + "\"";
    }
    
    if(tva >  1.78){
        var eqw = h * 1.78;
        var equiv = Math.round(Math.sqrt(h * h + eqw * eqw) * 10) / 10;
        tv1stat += "<br/>Equivalent 16:9 TV: " + equiv + "\"";
    }
     if(tva <  1.78){
        var eqh = w / 1.78;
        var equiv = Math.round(Math.sqrt(w * w + eqh * eqh) * 10) / 10;
        tvstat += "<br/>Equivalent 16:9 TV: " + equiv + "\"";
    }
    // Pixel density
    var pw = gbi("tv" + tvnum + "width").value;
    var ph = gbi("tv" + tvnum + "height").value;
    var pdens = Math.floor((ph * pw)/tvArea);
    tvstat += "<br/>Pixel Density: " + pdens + " pixels / sq. in.";
    gbi("tv" + tvnum + "stats").innerHTML = tvstat;
}

function sizetvs(){
    // Determine which TV is tallest. We'll use this as the limiting factor.
    
    var tallestTV = gbi("tv1size").value / Math.sqrt(gbi("tv1aspect").value * gbi("tv1aspect").value + 1);
    
    var tvheights = new Array();
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        tvheights[ii] = gbi("tv" + tv + "size").value / Math.sqrt(gbi("tv" + tv + "aspect").value * gbi("tv" + tv + "aspect").value + 1);
        if(tvheights[ii] > tallestTV) tallestTV = tvheights[ii];
    }
    
    // Iterate across the TVs. Scale them to the appropriate height.
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        tvh[tv] = Math.round((tvheights[ii] / tallestTV) * stdHeight);
    }
    
    // Now do width.
    for(var ii = 0; ii < numTVs; ii++){
        var tv = ii + 1;
        tvw[tv] = Math.round(tvh[tv] * gbi("tv" + tv + "aspect")[gbi("tv" + tv + "aspect").selectedIndex].value);
    }
    // Do the drawing of TVs and images.
    draw();
}

// document.getElementById is WAY too long of a name.
function gbi(id){
    return document.getElementById(id);	
}