// Must. Have. Data.
var feedURL = "http://ipv6.he.net/exhaustionFeed.php?platform=json";

// Queries go where?
var xmlObject = null;

// Current data. This is default "loading" data
var currentData = {
	startDate: -1,
	exhaustionDate: -1,
	unallocatedv4Blocks: -1,
	totalTLDs: -1,
	v6TLDs: -1,
	v6ASNs: -1,
	totalASNs: -1,
	v6NS: -1,
	v6Domains: -1,
	v6DomainsPerDay: -1,
	totalv4Blocks: -1,
	addrsPerBlock: -1
};

// Display update timer
var updateInterval = 100;
var timerUpdateID = -1;

// Data reload timer
var reloadInterval = 3600000;
var timerReloadID = -1;

function startup () {
	// Set the field labels
	if (useShort == true) {
		setContent ("title", locale.title_short);
		setContent ("ipv4_remaining_label", locale.ipv4_remaining_short);
		setContent ("ipv4_as_left_label", locale.ipv4_as_left_short);
		setContent ("ipv6_asns_label", locale.ipv6_asns_short);
		setContent ("ipv6_tlds_label", locale.ipv6_tlds_short);
		setContent ("ipv6_nss_label", locale.ipv6_nss_short);
		setContent ("ipv6_domains_label", locale.ipv6_domains_short);
		setContent ("days_label", locale.days_short);
		setContent ("exhaustion_label", locale.exhaustion_short);
		try {
			if (remoteIP) {
				setContent ("ip_addr_value", remoteIP);
				if (isIPv6) {
					setContent ("ip_addr_label", locale.ipv6_addr_short + ":");
					setContent ("ip_note", locale.have_ipv6_short);
				} else {
					setContent ("ip_addr_label", locale.ipv4_addr_short + ":");
					setContent ("ip_note", '<a target="_blank" href="http://tunnelbroker.net/">' + locale.get_ipv6_short + '</a>');
				}
			}
		}
		catch (err) {
			// Nothing here
		}
	} else {
		setContent ("title", locale.title);
		setContent ("ipv4_remaining_label", locale.ipv4_remaining + ":");
		setContent ("ipv4_as_left_label", locale.ipv4_as_left + ":");
		setContent ("ipv6_asns_label", locale.ipv6_asns + ":");
		setContent ("ipv6_tlds_label", locale.ipv6_tlds + ":");
		setContent ("ipv6_nss_label", locale.ipv6_nss + ":");
		setContent ("ipv6_domains_label", locale.ipv6_domains + ":");
		setContent ("days_label", locale.days);
		setContent ("exhaustion_label", locale.exhaustion);
		try {
			if (remoteIP) {
				setContent ("ip_addr_value", remoteIP);
				if (isIPv6) {
					setContent ("ip_addr_label", locale.ipv6_addr + ":");
					setContent ("ip_note", locale.have_ipv6);
				} else {
					setContent ("ip_addr_label", locale.ipv4_addr + ":");
					setContent ("ip_note", '<a target="_blank" href="http://tunnelbroker.net/">' + locale.get_ipv6 + '</a>');
				}
			}
		}
		catch (err) {
			// Nothing here
		}
	}
	
	// Set the fields to "loading" values
	setContent ("ipv4_remaining_value", "<i>?</i>");
	setContent ("ipv4_as_left_value", "<i>?</i>");
	setContent ("ipv4_as_left_values", "");
	setContent ("ipv4_asns_value", "<i>?</i>");
	setContent ("ipv4_asns_values", "");
	setContent ("ipv4_tlds_value", "<i>?</i>");
	setContent ("ipv4_tlds_values", "");
	setContent ("ipv6_nss_value", "<i>?</i>");
	setContent ("ipv6_domains_value", "<i>?</i>");
	setContent ("days_value", "<i>?</i>");
	
	// Look for an overlay. Make it visible if we're not in a sidebar
	var element = document.getElementById ('link_overlay');
	if (element) {
		try {
			if (System) {
				
			}
		}
		catch (err) {
			element.style.display = 'block';
		}
	}
	
	// Get the first data set
	getFile (feedURL, updateData);
}

function updateDisplay () {
	var temp;
	
	temp = Math.floor (currentData.startAddrs * ((currentData.exhaustionDate - now ()) / (currentData.exhaustionDate - currentData.startDate)));
	if (temp < 0) {
		temp = 0;
	}
	setContent ("ipv4_remaining_value", commaize (temp));
	
	temp = Math.floor ((currentData.exhaustionDate - now ()) / 86400);
	if (temp < 0) {
		temp = 0;
	}
	setContent ("days_value", temp);
	setContent ("ipv6_domains_value", commaize (Math.floor (currentData.v6Domains + ((currentData.v6DomainsPerDay / 86400) * (now () - currentData.midnight)))));
}

function setContent (id, content) {
	var element = document.getElementById (id);
	if (element) {
		element.innerHTML = content;
	}
}

function dateToEpoch (string, year, month, day) {
	var str = String (string);
	var parts = str.split ('-');
	var date = new Date (parts [year], parts [month] - 1, parts [day]);
	return (date.getTime () / 1000);
}

function now () {
	var date = new Date;
	return (date.getTime () / 1000);
}

function todayMidnight () {
	var date = new Date;
	var midnight = new Date (date.getFullYear (), date.getMonth (), date.getDate (), 0, 0, 0);
	return (midnight.getTime () / 1000);
}

function commaize (number) {
	var numberstring = String (number);
	var x = numberstring.split (".");
	var x1 = x [0];
	var x2 = x.length > 1 ? "." + x [1] : "";
	var regex = /(\d+)(\d{3})/;
	while (regex.test (x1)) {
		x1 = x1.replace (regex, "$1" + "," + "$2");
	}
	return (x1 + x2);
}

function createRequest (callback) {
	var XMLObj = null;
	try {
		XMLObj = new XMLHttpRequest ();
	} catch (e) {
		try {
			XMLObj = new ActiveXObject ("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				XMLObj = new ActiveXObject ("Microsoft.XMLHTTP");
			} catch (e) {
				return null;
			}
		}
	}
	if (XMLObj) {
		XMLObj.onreadystatechange = callback;
	}
	return (XMLObj);
}

function getFile (url, callback) {
	xmlObject = createRequest (callback);
	if (xmlObject) {
		xmlObject.open ("GET", url, true);
		xmlObject.send (null);
	}
	timerReloadID = setTimeout ("getFile(feedURL,updateData)", reloadInterval);
}

function updateData (response) {
	if ((xmlObject.readyState == 4) && (xmlObject.status == 200)) {
		// Stop updates to the display while we're loading data
		if (timerUpdateID != -1) {
			clearInterval (timerUpdateID);
			timerUpdateID = -1;
		}
		
		// JSON
		currentData = eval ("(" + xmlObject.responseText + ")");
		
		// Convert YYYY-MM-DD to epoch
		currentData.startDate = dateToEpoch (currentData.startDate, 0, 1, 2);
		currentData.exhaustionDate = dateToEpoch (currentData.exhaustionDate, 0, 1, 2);
		
		// Convert any strings to integers
		currentData.unallocatedv4Blocks = parseInt (currentData.unallocatedv4Blocks, 10);
		currentData.totalTLDs = parseInt (currentData.totalTLDs, 10);
		currentData.v6TLDs = parseInt (currentData.v6TLDs, 10);
		currentData.v6ASNs = parseInt (currentData.v6ASNs, 10);
		currentData.totalASNs = parseInt (currentData.totalASNs, 10);
		currentData.v6NS = parseInt (currentData.v6NS, 10);
		currentData.v6Domains = parseInt (currentData.v6Domains, 10);
		currentData.v6DomainsPerDay = parseInt (currentData.v6DomainsPerDay, 10);
		
		// Add extra useful data
		currentData.totalv4Blocks = 256;
		currentData.addrsPerBlock = Math.pow (2, 24);
		currentData.startAddrs = currentData.unallocatedv4Blocks * currentData.addrsPerBlock;
		currentData.midnight = todayMidnight ();
		
		// Set the "static" values
		setContent ("ipv4_as_left_value", Math.floor ((currentData.unallocatedv4Blocks / currentData.totalv4Blocks) * 100) + "%");
		setContent ("ipv4_as_left_values", "(" + commaize (currentData.unallocatedv4Blocks) + "/" + commaize (currentData.totalv4Blocks) + ")");
		setContent ("ipv4_asns_value", Math.floor ((currentData.v6ASNs / currentData.totalASNs) * 100) + "%");
		setContent ("ipv4_asns_values", "(" + commaize (currentData.v6ASNs) + "/" + commaize (currentData.totalASNs) + ")");
		setContent ("ipv4_tlds_value", Math.floor ((currentData.v6TLDs / currentData.totalTLDs) * 100) + "%");
		setContent ("ipv4_tlds_values", "(" + commaize (currentData.v6TLDs) + "/" + commaize (currentData.totalTLDs) + ")");
		setContent ("ipv6_nss_value", commaize (currentData.v6NS));
		
		// Update the display
		updateDisplay ();
		
		// Restart the display update timer
		timerUpdateID = setInterval ("updateDisplay()", updateInterval);
	}
}