var ideoneSubmissions = new Array(); // stores references to all submission nodes
var ideoneLoadedSubmissions = new Array(); // for each code stores SID of the latest loaded submission

// Some helper functions

function ideoneCheckIfIE() {
	return navigator.appName == 'Microsoft Internet Explorer';
}

function ideoneHasClass(element, clazz) {
	return element.className.search(clazz) != -1;
}

function ideoneAddClass(element, clazz) {
	if (!ideoneHasClass(element, clazz)) {
		if (element.className.length > 0) {
			element.className += ' ';
		}
		element.className += clazz;
	}
}

function ideoneRemoveClass(element, clazz) {
	if (element.className.search(clazz) != -1) {
		element.className = element.className.replace(new RegExp('( )?' + clazz), '');
	}
}

/**
 * Change the visibility of child nodes
 */
function ideoneToggleHidden(node) {
	for (var i = 0; i < node.childNodes.length; i++) {
		var element = node.childNodes[i];
		if (ideoneHasClass(element, 'ideone_hidden')) {
			ideoneRemoveClass(element, 'ideone_hidden');
		} else {
			ideoneAddClass(element, 'ideone_hidden');
		}
	}
}

/**
 * Show submission panel
 */
function ideoneShowSubmissions(cid) {
	var code = document.getElementById('ideone_cid_' + cid);
	var panel = document.getElementById('ideone_panel_cid_' + cid);
	var theswitch = document.getElementById('ideone_switch_cid_' + cid);

	ideoneAddClass(code, 'ideone_hidden');
	ideoneRemoveClass(panel, 'ideone_hidden');

	ideoneToggleHidden(theswitch);

	if (!ideoneLoadedSubmissions.hasOwnProperty(cid)) {
		ideoneLoadedSubmissions[cid] = 0;
	}
	ideoneLoadSubmissions(cid);
}

/**
 * Hide submission panel
 */
function ideoneHideSubmissions(cid) {
	var code = document.getElementById('ideone_cid_' + cid);
	var panel = document.getElementById('ideone_panel_cid_' + cid);
	var theswitch = document.getElementById('ideone_switch_cid_' + cid);

	ideoneRemoveClass(code, 'ideone_hidden');
	ideoneAddClass(panel, 'ideone_hidden');

	ideoneToggleHidden(theswitch);
}

/**
 * Show outdated submissions
 */
function ideoneShowOutdatedSubmissions(cid) {
	var theswitch = document.getElementById('ideone_outdated_switch_cid_' + cid);
	var submissions = document.getElementById('ideone_outdated_submissions_cid_' + cid);

	ideoneToggleHidden(theswitch);

	ideoneRemoveClass(submissions, 'ideone_hidden');
}

/**
 * Hide outdated submissions
 */
function ideoneHideOutdatedSubmissions(cid) {
	var theswitch = document.getElementById('ideone_outdated_switch_cid_' + cid);
	var submissions = document.getElementById('ideone_outdated_submissions_cid_' + cid);

	ideoneToggleHidden(theswitch);

	ideoneAddClass(submissions, 'ideone_hidden');
}

/**
 * Show/hide details (stdin, stdout, stderr, compiler messages and link to Ideone.com) about the submission
 */
function ideoneSubmissionDetailsSwitch(sid) {
	var theswitch = document.getElementById('ideone_submission_switch_sid_' + sid);
	var details = document.getElementById('ideone_submission_details_sid_' + sid);

	ideoneToggleHidden(theswitch);

	if (ideoneHasClass(details, 'ideone_hidden')) {
		ideoneRemoveClass(details, 'ideone_hidden');
	} else {
		ideoneAddClass(details, 'ideone_hidden');
	}
}

/**
 * Show/hide input for new submission
 */
function ideoneNewSubmission(cid) {
	var newSubmission = document.getElementById('ideone_new_submission_cid_' + cid);
	ideoneToggleHidden(newSubmission);
}

/**
 * Call method implemented in /ideone/ideone.php
 */
function ideoneRemoteCall(method, params, callback) {
	var req = new XMLHttpRequest();

	var data = 'method=' + method;
	for (var name in params) {
		data += '&' + name + '=' + params[name];
	}
	req.open('POST', './ideone/ideone.php', true);
	req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
	req.onreadystatechange = function() {callback(req)};
	req.send(data);
}

/**
 * Submit code with input to Ideone.com
 */
function ideoneSubmit(cid) {
	var parentNode = document.getElementById('ideone_submissions_cid_' + cid);

	var element = document.createElement('li');
	element.className = 'loader';
	element.appendChild(document.createTextNode('Loading...'));

	if (parentNode.childNodes.length > 1) {
		parentNode.insertBefore(element, parentNode.childNodes[1]);
	} else {
		parentNode.appendChild(element);
	}

	var callback = function(req) {
		if (req.readyState == 4 && req.status == 200) {
			var error = req.responseXML.getElementsByTagName('error')[0].firstChild.data;
			if (error == 'OK') {
				parentNode.removeChild(element);
				ideoneUpdateSubmission(req.responseXML.getElementsByTagName('submission')[0], parentNode, false);
			} else	{
				alert('ERROR: ' + error);
				return;
			}
		}
	};
	ideoneRemoteCall('createSubmission', {'cid' : cid, 'input' : document.forms['ideone_new_submission_form_cid_' + cid].input.value}, callback);
}

/**
 * Create node with submission details
 */
function ideoneCreateSubmissionElement(submission, outdated) {
	var element = document.createElement('li');

	if (submission['status'] != 0) {
		element.className = 'loader';
		if (submission['status'] == null) {
			element.appendChild(document.createTextNode('Loading...'));
		} else if (submission['status'] < 0) {
			element.appendChild(document.createTextNode('Waiting for compilation...'));
		} else if (submission['status'] == 1) {
			element.appendChild(document.createTextNode('Compilation...'));
		} else if (submission['status'] == 3) {
			element.appendChild(document.createTextNode('Running...'));
		}
	} else {
		var overall = document.createElement('div');
		overall.className = 'ideone_submission_overall';
		var space = '\u00A0\u00A0\u00A0\u00A0'; // 4 x '&nbsp;'

		overall.appendChild(document.createTextNode('#' + submission['id'] + space + submission['date'] + space + 'result:\u00A0'));

		var showPerformanceInfo = true;

		var result = document.createElement('span');
		switch (parseInt(submission['result'])) {
			case 0 : //not running
				result.appendChild(document.createTextNode('not running'));
				showPerformanceInfo = false;
				break;
			case 11: //compilation error
				result.className = 'ideone_result_error2';
				result.appendChild(document.createTextNode('compilation error'));
				showPerformanceInfo = false;
				break;
			case 12: //runtime error
				result.className = 'ideone_result_error2';
				result.appendChild(document.createTextNode('runtime error'));
				break;
			case 13: //time limit exceeded
				result.className = 'ideone_result_error1';
				result.appendChild(document.createTextNode('time limit exceeded'));
				break;
			case 15: //success
				result.className = 'ideone_result_ok';
				result.appendChild(document.createTextNode('success'));
				break;
			case 17: //memory limit exceeded
				result.className = 'ideone_result_error1';
				result.appendChild(document.createTextNode('memory limit exceeded'));
				break;
			case 19: //illegal system call
				result.className = 'ideone_result_error2';
				result.appendChild(document.createTextNode('illegal system call'));
				break;
			case 20: //internal error
				result.className = 'ideone_result_error2';
				result.appendChild(document.createTextNode('internal error'));
				showPerformanceInfo = false;
				break;

		}
		overall.appendChild(result);

		if (showPerformanceInfo) {
			overall.appendChild(document.createTextNode(space + 'time:\u00A0'));
			if (submission['time'] == '-1') {
				overall.appendChild(document.createTextNode('\u221E'));
			} else {
				overall.appendChild(document.createTextNode(submission['time'] + '\u00A0s'));
			}

			overall.appendChild(document.createTextNode(space + 'memory:\u00A0' + submission['memory'] + '\u00A0kB'));

			if (submission['result'] != 15) {
				overall.appendChild(document.createTextNode(space + 'signal:\u00A0'));
				overall.appendChild(document.createTextNode(submission['signal']));
			}
		}

		if (outdated) {
			overall.appendChild(document.createTextNode(space));
			var theoutdated = document.createElement('span');
			theoutdated.className = 'ideone_outdated';
			theoutdated.appendChild(document.createTextNode('OUTDATED'));
			overall.appendChild(theoutdated);
		}

		element.appendChild(overall);

		var details_switch = document.createElement('div');
		details_switch.id = 'ideone_submission_switch_sid_' + submission['id'];
		details_switch.className = 'ideone_submission_details_switch';

		var show = document.createElement('a');
		show.setAttribute('href', '#');
		show.onclick = function() {ideoneSubmissionDetailsSwitch(submission['id']);return false;};
		show.appendChild(document.createTextNode('More'));
		details_switch.appendChild(show);

		var hide = document.createElement('a');
		hide.className = 'ideone_hidden';
		hide.setAttribute('href', '#');
		hide.onclick = function() {ideoneSubmissionDetailsSwitch(submission['id']);return false;};
		hide.appendChild(document.createTextNode('Less'));
		details_switch.appendChild(hide);

		element.appendChild(details_switch);

		var clear = document.createElement('div');
		clear.className = 'ideone_clear';
		element.appendChild(clear);

		var details = document.createElement('div');
		details.id = 'ideone_submission_details_sid_' + submission['id'];
		details.className = 'ideone_hidden';


		if (submission['input'] != null) {
			details.appendChild(document.createTextNode('Input:'));
			details.appendChild(document.createElement('br'));
			if (!ideoneCheckIfIE()) {
				var input = document.createElement('pre');
				input.appendChild(document.createTextNode(submission['input']));
				details.appendChild(input);
			} else {
				details.innerHTML += '<pre>' + submission['input'] + '</pre>';
			}
		}

		if (submission['output'] != null) {
			details.appendChild(document.createTextNode('Output:'));
			details.appendChild(document.createElement('br'));
			if (!ideoneCheckIfIE()) {
				var output = document.createElement('pre');
				output.appendChild(document.createTextNode(submission['output']));
				details.appendChild(output);
			} else {
				details.innerHTML += '<pre>' + submission['output'] + '</pre>';
			}
		}

		if (submission['stderr'] != null) {
			details.appendChild(document.createTextNode('Error:'));
			details.appendChild(document.createElement('br'));
			if (!ideoneCheckIfIE()) {
				var error = document.createElement('pre');
				error.appendChild(document.createTextNode(submission['stderr']));
				details.appendChild(error);
			} else {
				details.innerHTML += '<pre>' + submission['stderr'] + '</pre>';
			}
		}

		if (submission['cmpinfo'] != null) {
			details.appendChild(document.createTextNode('Compiler:'));
			details.appendChild(document.createElement('br'));
			if (!ideoneCheckIfIE()) {
				var compiler = document.createElement('pre');
				compiler.appendChild(document.createTextNode(submission['cmpinfo']));
				details.appendChild(compiler);
			} else {
				details.innerHTML += '<pre>' + submission['cmpinfo'] + '</pre>';
			}
		}

		details.appendChild(document.createTextNode('See submission at '));
		var link = document.createElement('a');
		link.setAttribute('href', 'http://ideone.com/' + submission['link']);
		link.setAttribute('target', '_blank');
		link.appendChild(document.createTextNode('Ideone.com/' + submission['link']));
		details.appendChild(link);

		element.appendChild(details);
	}

	return element;
}

/**
 * Update or create new submission entry
 */
function ideoneUpdateSubmission(submissionNode, target, outdated) {
	var submission = new Array();

	for (var i = 0; i < submissionNode.childNodes.length; i++) {
		var child = submissionNode.childNodes[i];
		submission[child.tagName] = (child.firstChild != null) ? child.firstChild.data : null;
	}

	var element = ideoneCreateSubmissionElement(submission, outdated);

	if (!ideoneSubmissions.hasOwnProperty(submission['code'])) {
		ideoneSubmissions[submission['code']] = new Array();
	}

	var submissionsArray = ideoneSubmissions[submission['code']];

	if (submissionsArray.hasOwnProperty(submission['id'])) {
		target.replaceChild(element, submissionsArray[submission['id']]['node']);
		submissionsArray[submission['id']]['node'] = element;
	} else {
		var id = -1;
		for (var i in submissionsArray) {
			if (outdated == submissionsArray[i]['outdated'] && parseInt(i) > id && parseInt(i) < parseInt(submission['id'])) {
				id = i;
			}
		}
		var elementAfter = (id != -1) ? submissionsArray[id]['node'] : null;
		target.insertBefore(element, elementAfter);
		submissionsArray[parseInt(submission['id'])] = {'node' : element, 'outdated' : outdated};
	}

	if (!submission.hasOwnProperty('status') || submission['status'] != 0) {
		var callback = function(req) {
			if (req.readyState == 4 && req.status == 200) {
				var error = req.responseXML.getElementsByTagName('error')[0].firstChild.data;
				if (error == 'OK') {
					ideoneUpdateSubmission(req.responseXML.getElementsByTagName('submission')[0], target, outdated);
				} else {
					alert('ERROR: ' + error);
					return;
				}
			}
		}
		ideoneRemoteCall('getSubmissionDetails', {'sid' : submission['id']}, callback);
	}
}

/**
 * Load submissions
 */
function ideoneLoadSubmissions(cid) {
	var headerLoader = document.getElementById('ideone_header_loader_cid_' + cid);
	ideoneRemoveClass(headerLoader, 'ideone_hidden');
	var callback = function(req) {
		if (req.readyState == 4 && req.status == 200) {
			ideoneAddClass(headerLoader, 'ideone_hidden');
			var error = req.responseXML.getElementsByTagName('error')[0].firstChild.data;
			if (error == 'OK') {
				var submissions = req.responseXML.getElementsByTagName('submissions')[0];
				for (var i = 0; i < submissions.childNodes.length; i++) {
					var child = submissions.childNodes[i];
					var id = parseInt(child.getElementsByTagName('id')[0].firstChild.data);
					if (id > ideoneLoadedSubmissions[cid]) {
						ideoneLoadedSubmissions[cid] = id;
					}
					ideoneUpdateSubmission(child, document.getElementById('ideone_submissions_cid_' + cid), false);
				}

				var outdatedSubmissions = req.responseXML.getElementsByTagName('outdatedSubmissions')[0];
				var panelOutdated = document.getElementById('ideone_panel_outdated_cid_' + cid);
				if (outdatedSubmissions.childNodes.length > 0) {
					ideoneRemoveClass(panelOutdated, 'ideone_hidden');
				}
				for (var i = 0; i < outdatedSubmissions.childNodes.length; i++) {
					var child = outdatedSubmissions.childNodes[i];
					var id = parseInt(child.getElementsByTagName('id')[0].firstChild.data);
					if (id > ideoneLoadedSubmissions[cid]) {
						ideoneLoadedSubmissions[cid] = id;
					}
					ideoneUpdateSubmission(child, document.getElementById('ideone_outdated_submissions_cid_' + cid), true);
				}
			} else {
				alert('ERROR: ' + error);
				return;
			}
		}
	}
	ideoneRemoteCall('getSubmissions', {'cid' : cid, 'sid' : ideoneLoadedSubmissions[cid]}, callback);
}
