/*******************************************************************************
 * 
 * Author: Justin Samuel <justin /at/ justinsamuel /dot/ com>
 * Date: 2008-04-25
 * License: GPL
 * 
 * UI utilities for descrack.
 * 
 * This file relies on:
 * + descrack_util.js ???
 * 
 ******************************************************************************/

var useLog = false; // whether log info should be collected and displayed
var errorReportEmail = "justin /at/ justinsamuel /dot/ com" // shown in error message

var possibleKeys = 72057594037927936; // this ends up stored as a float
var secondsPerYear = 3600 * 24 * 365;

var statusDiv = null; // local key search status
var statsDiv = null; // local key search statistics
var commStatusDiv = null; // local key search server communication status

var overallStatusDiv = null; // global key search status
var overallStatsDiv = null; // global statistics
var overallCommStatusDiv = null; // global stats server communication status

var logDiv = null; // log output
var errorDiv = null; // error output

var startedDiv = null;
var unstartedDiv = null;
var pausedDiv = null;
var runningDiv = null;

var onlineDiv = null;
var offlineDiv = null;

var loggingEnabledDiv = null;
var loggingDisabledDiv = null;

var logText = '';

window.onload = setupUI; // run setupUI() when html page done loading

function setupUI() {
	statusDiv = document.getElementById('localStatus');
	statsDiv = document.getElementById('localStatistics');
	commStatusDiv = document.getElementById('localCommStatus');

    overallStatusDiv = document.getElementById('overallStatus');
    overallStatsDiv = document.getElementById('overallStatistics');
    overallCommStatusDiv = document.getElementById('overallCommStatus');
	
	logDiv = document.getElementById('log');
	errorDiv = document.getElementById('errorLog');

	startedDiv = document.getElementById('started');
	unstartedDiv = document.getElementById('unstarted');
	pausedDiv = document.getElementById('paused');
	runningDiv = document.getElementById('running');
    
    onlineDiv = document.getElementById('online');
    offlineDiv = document.getElementById('offline');

    loggingEnabledDiv = document.getElementById('loggingEnabled');
    loggingDisabledDiv = document.getElementById('loggingDisabled');
    
    // in case this was a browser reload, need to force this
    setOnline();
    document.getElementById('delay').selectedIndex = 0;
    setFormSelection('onlineButton', true);
    setFormSelection('offlineButton', false);
    
    requestStats();
}

function status(text) {
	statusDiv.innerHTML = text;
}

function commStatus(isCommunicating) {
	if (isCommunicating) {
		commStatusDiv.innerHTML = 'Communicating...';
	} else {
		commStatusDiv.innerHTML = '<br />';
	}
}

function setLogging(flag) {
	useLog = flag;
    if (flag) {
        hide(loggingDisabledDiv);
        show(loggingEnabledDiv);
    } else {
        show(loggingDisabledDiv);
        hide(loggingEnabledDiv);
    }
}

function log(text) {
	if (useLog) {
		logText += text + '<br />';
		logDiv.innerHTML = logText;
	}
}

function clearLog() {
	logText = '';
	logDiv.innerHTML = logText;
}

function logError(text) {
	text = "<h2>An error was encountered:</h2>" + text + "<br />";
	text += '<b>Please report this to: ' + errorReportEmail + "</b>";
	errorDiv.innerHTML = text
	show(errorDiv);
}

function updateStats() {
	var text = '';
	text += 'Keys tested: ' + bytesTested * 128 + '<br />';
	text += 'Total time: ' + totalTime / 1000 + ' s <br />';
	var keysPerSecond = (bytesTested * 128) / totalTime * 1000; // time is in
																// milliseconds
	text += 'Keys per second: ' + Math.floor(keysPerSecond) + ' <br />';
	var avgYears = possibleKeys / keysPerSecond / secondsPerYear / 2;
	text += 'Avg. browser years to find key: ' + Math.floor(avgYears)
			+ ' <br />';
	statsDiv.innerHTML = text;
}

function printTime() {
	log("Total elapsed time: " + totalTime / 1000 + " s");
}

/*
 * Begin testing keys.
 */
function start() {
	started = true;

	hide(unstartedDiv);
	show(startedDiv);
	show(runningDiv);

	online = getFormSelection('onlineButton');

	if (!online) {
        setStartKey(getFormStartKey());
        setByteRange(getFormByteRange());
        setPlaintext(getFormPlaintext());
        setCiphertext(getFormCiphertext());
	}

	desCrack();
}

/*
 * Stop testing keys and return to original state.
 */
function stop() {
	started = false;
	show(unstartedDiv);
}

/*
 * Set whether key testing is paused.
 */
function setPaused(flag) {
	paused = flag;
	if (flag) {
		hide(runningDiv);
		show(pausedDiv);
	} else {
		show(runningDiv);
		hide(pausedDiv);
	}
}

function pause() {
	setPaused(true);
}

function resume() {
	setPaused(false);
}

function reset() {
	started = false;
	resetLocalStats();
	clearLog();
    resume(); // to unpause
	hide(startedDiv);
	show(unstartedDiv);
}

/*
 * Get true/false of whether a radio button is selected.
 */
function getFormSelection(id) {
	return document.getElementById(id).checked;
}

/*
 * Set true/false of whether a radio button is selected.
 */
function setFormSelection(id, checked) {
    document.getElementById(id).checked = checked;
}

/*
 * Get the value of an input.
 */
function getFormValue(id) {
    return document.getElementById(id).value;
}

/*
 * Set the value of an input.
 */
function setFormValue(id, value) {
    document.getElementById(id).value = value;
}

function hide(el) {
	el.style.display = 'none';
}

function show(el) {
	el.style.display = 'block';
}

function setOnline() {
    hide(offlineDiv);
    show(onlineDiv);
}

function setOffline() {
    hide(onlineDiv);
    show(offlineDiv);
}

function getFormStartKey() {
	var newStartKey = new Array(8);
	newStartKey[0] = parseInt(getFormValue('keyByte1'));
	newStartKey[1] = parseInt(getFormValue('keyByte2'));
	newStartKey[2] = parseInt(getFormValue('keyByte3'));
	newStartKey[3] = parseInt(getFormValue('keyByte4'));
	newStartKey[4] = parseInt(getFormValue('keyByte5'));
	newStartKey[5] = parseInt(getFormValue('keyByte6'));
	newStartKey[6] = parseInt(getFormValue('keyByte7'));
	newStartKey[7] = parseInt(getFormValue('keyByte8'));
	return newStartKey;
}

function setFormStartKey(newStartKey) {
    setFormValue('keyByte1', newStartKey[0]);
    setFormValue('keyByte2', newStartKey[1]);
    setFormValue('keyByte3', newStartKey[2]);
    setFormValue('keyByte4', newStartKey[3]);
    setFormValue('keyByte5', newStartKey[4]);
    setFormValue('keyByte6', newStartKey[5]);
    setFormValue('keyByte7', newStartKey[6]);
    setFormValue('keyByte8', newStartKey[7]);
}

function getFormByteRange() {
    return parseInt(getFormValue('byteRange'));
}

function setFormByteRange(newByteRange) {
    setFormValue('byteRange', newByteRange);
}

function getFormPlaintext() {
    var newPt = new Array(8);
    newPt[0] = parseInt(getFormValue('ptByte1'));
    newPt[1] = parseInt(getFormValue('ptByte2'));
    newPt[2] = parseInt(getFormValue('ptByte3'));
    newPt[3] = parseInt(getFormValue('ptByte4'));
    newPt[4] = parseInt(getFormValue('ptByte5'));
    newPt[5] = parseInt(getFormValue('ptByte6'));
    newPt[6] = parseInt(getFormValue('ptByte7'));
    newPt[7] = parseInt(getFormValue('ptByte8'));
    return newPt;
}

function setFormPlaintext(newPlaintext) {
    setFormValue('ptByte1', newPlaintext[0]);
    setFormValue('ptByte2', newPlaintext[1]);
    setFormValue('ptByte3', newPlaintext[2]);
    setFormValue('ptByte4', newPlaintext[3]);
    setFormValue('ptByte5', newPlaintext[4]);
    setFormValue('ptByte6', newPlaintext[5]);
    setFormValue('ptByte7', newPlaintext[6]);
    setFormValue('ptByte8', newPlaintext[7]);
}

function getFormCiphertext() {
    var newCt = new Array(8);
    newCt[0] = parseInt(getFormValue('ctByte1'));
    newCt[1] = parseInt(getFormValue('ctByte2'));
    newCt[2] = parseInt(getFormValue('ctByte3'));
    newCt[3] = parseInt(getFormValue('ctByte4'));
    newCt[4] = parseInt(getFormValue('ctByte5'));
    newCt[5] = parseInt(getFormValue('ctByte6'));
    newCt[6] = parseInt(getFormValue('ctByte7'));
    newCt[7] = parseInt(getFormValue('ctByte8'));
    return newCt;
}

function setFormCiphertext(newCiphertext) {
    setFormValue('ctByte1', newCiphertext[0]);
    setFormValue('ctByte2', newCiphertext[1]);
    setFormValue('ctByte3', newCiphertext[2]);
    setFormValue('ctByte4', newCiphertext[3]);
    setFormValue('ctByte5', newCiphertext[4]);
    setFormValue('ctByte6', newCiphertext[5]);
    setFormValue('ctByte7', newCiphertext[6]);
    setFormValue('ctByte8', newCiphertext[7]);
}

function setFormToSampleData(sampleData, sampleNumber) {
    setFormStartKey(sampleData.startKey[sampleNumber]);
    setFormByteRange(sampleData.byteRange[sampleNumber]);
    setFormPlaintext(sampleData.pt[sampleNumber]);
    setFormCiphertext(sampleData.ct[sampleNumber]);
}
