var myApp = {
	questionArr: [],
	mathTest: function (args) {
		if (!args) {
			args = {};
		}
		args.container = (typeof args.container === "string") ? args.container : "math";
		args.difficulty = (typeof args.difficulty === "number") ? Math.abs(Math.floor(args.difficulty)) : 100;
		args.numproblems = (typeof args.numproblems === "number") ? Math.abs(Math.floor(args.numproblems)) : 100;
		args.columns = (typeof args.columns === "number") ? Math.floor(args.columns) : 10;
		// 0 = addition, 1 = subtraction, 2 = multiplication, 3 = division
		args.questiontypes = (Object.prototype.toString.apply(args.questiontypes) === '[object Array]') ? args.questiontypes : [0, 1, 2];
		if (!document || !document.getElementById || !document.getElementById(args.container)) {
			return;
		}
		myApp.questionArr = []; //clear questions from last test
		var container = document.getElementById(args.container);
		container.style.display = "block";
		if (container.getElementsByTagName("ul").length == 0) {
			container.appendChild(document.createElement("ul"));
		}
		var i, j, num1, opIndex, opType, num2,
		mList = container.getElementsByTagName("ul")[0],
		sp = document.createElement("span"),
		clear = document.createElement("li"),
		tmp,
		problems = {
			add: document.createElement("li"),
			sub: null,
			mul: null,
			div: null
		},
		members = [],
		operators = [
			{type: "add", op: "+", mathop: "+"},
			{type: "sub", op: "-", mathop: "-"},
			{type: "mul", op: "&times;", mathop: "*"},
			{type: "div", op: "/", mathop: "/"}
		],
		tmpNode = null,
		getRnd = function( max, min ) {
			max = parseInt( max );
			max = (isNaN( max )) ? 0 : max;
			min = parseInt( min );
			min = (isNaN( min )) ? 0 : min;
			return Math.floor( Math.random() * (max - min + 1) + min );
		},
		hasDivision = (args.questiontypes.join("").indexOf("3") != -1),
		numDigits = 0,
		extraClass = "";
		if (!hasDivision) {
			numDigits = args.difficulty.toString().split("").length;
			if (numDigits == 1) {
				numDigits = 2;
			}
			extraClass = "width" + numDigits + "digit";
		}
		clear.className = "newline";
		sp.className = "n1";
		problems.add.appendChild(sp.cloneNode(true));
		sp.className = "op";
		problems.add.appendChild(sp.cloneNode(true));
		sp.className = "n2";
		problems.add.appendChild(sp.cloneNode(true));
		sp.className = "ans";
		problems.add.appendChild(sp.cloneNode(true));
		problems.sub = problems.add.cloneNode(true);
		problems.mul = problems.add.cloneNode(true);
		problems.div = problems.add.cloneNode(true);
		problems.add.className = "add";
		problems.sub.className = "sub";
		problems.mul.className = "mul";
		problems.div.className = "div";
		if (args.columns > 0) {
			if (numDigits > 0) {
				container.style.width = (args.columns * (numDigits / 2 + 2.9)) + "em";
			} else {
				container.style.width = (args.columns * 6) + "em";
			}
		} else {
			container.style.width = "100%";
		}
		for (i = 0; i < args.numproblems; i++) {
			if (args.columns > 0 && i > 0 && i % args.columns == 0) {
				mList.appendChild(clear.cloneNode(true));
			}
			num1 = getRnd(args.difficulty, 1);
			//opIndex = getRnd(3); 
			if (args.questiontypes.length > 0) {
				opIndex = args.questiontypes[getRnd(args.questiontypes.length - 1)];
			} else {
				opIndex = 0;
			}
			opType = operators[opIndex].type;
			num2 = getRnd(args.difficulty, 1);
			tmpNode = problems[opType].cloneNode(true);
			if (extraClass.length > 0) {
				tmpNode.className += " " + extraClass;
			}
			switch (opType) {
				case "add":
				case "mul":
				case "sub":
					// ensure num1 is the greater of the two numbers to prevent negative answers
					// (so that little kids' and some adults' brains don't explode)
					if (num1 < num2) {
						tmp = num1;
						num1 = num2;
						num2 = tmp;
					}
					break;
				case "div":
					num1 *= num2;
					break;
			}
			myApp.questionArr.push("" + num1 + operators[opIndex].mathop + num2);
			members = tmpNode.getElementsByTagName("span");
			for (j = 0; j < members.length; j++) {
				switch (members[j].className) {
					case "n1":
						members[j].innerHTML = num1;
						break;
					case "op":
						members[j].innerHTML = operators[opIndex].op;
						break;
					case "n2":
						members[j].innerHTML = num2;
						break;
					case "ans":
						members[j].innerHTML = "<input type=\"text\" id=\"a" + i + "\" size=\"4\" title=\"" + num1 + operators[opIndex].mathop + num2 + "\" onfocus=\"this.className='';\" onblur=\"myApp.checkAnswer(this);\" onchange=\"myApp.checkAnswer(this);\" />";
						break;
				}
			}
			mList.appendChild(tmpNode);
		}
	},
	checkAnswer: function(element) {
		var userAnswer = parseInt(element.value.replace(/\D/gi, ""), 10),
		questionIndex = parseInt(element.id.replace(/\D/gi, ""), 10),
		question = (!isNaN(questionIndex) && questionIndex >= 0 && questionIndex < myApp.questionArr.length) ? myApp.questionArr[questionIndex] : "-1",
		correct = false;
		if (question.match(/\d+[\+\-\*\/]{1}\d+/)) {
			if (!isNaN(userAnswer) && eval(question) == userAnswer) {
				element.className = "correct";
				//element.disabled = true;
				correct = true;
			} else {
				if (isNaN(userAnswer)) userAnswer = "";
				if (userAnswer.length == 0) {
					element.className = "";
				} else {
					element.className = "incorrect";
				}
			}
			element.value = userAnswer;
		} else {
			//invalid question type?
		}
		return correct;
	},
	generateTestFromForm: function(f) {
		document.getElementById("math").innerHTML = "";
		var qTypeArr = [];
		if (f.qt0.checked) qTypeArr.push(0);
		if (f.qt1.checked) qTypeArr.push(1);
		if (f.qt2.checked) qTypeArr.push(2);
		if (f.qt3.checked) qTypeArr.push(3);
		myApp.mathTest({
			container: "math",
			difficulty: parseInt(f.difficulty.value, 10),
			numproblems: parseInt(f.numproblems.value, 10),
			columns: parseInt(f.columns.value, 10),
			questiontypes: qTypeArr
		});
	},
	setFocusToNextEmpty: function(f) {
		var i, e;
		for (i = 0; i < f.length; i++) {
			e = f.elements[i];
			if (e.value.length == 0) {
				e.focus();
				if (e.offsetLeft && e.offsetTop) {
					window.scrollTo(e.offsetLeft, e.offsetTop);
				}
				break;
			}
		}
		return false;
	},
	checkAllAnswers: function(f) {
		var i, e, numCorrect = 0, numIncorrect = 0, numInc = 0;
		for (i = 0; i < f.length; i++) {
			e = f.elements[i];
			if (e.type == "text") {
				if (myApp.checkAnswer(e)) {
					numCorrect++;
				} else if (e.value.length == 0){
					numInc++;
				} else {
					numIncorrect++;
				}
			}
		}
		alert("Correct: " + numCorrect + "\nIncorrect: " + numIncorrect + "\nIncomplete: " + numInc);
		myApp.setFocusToNextEmpty(f);
	}
};

function printPage() {
	if (window.print) {
		window.print();
	} else {
		alert("Press the \"Print\" button in your browser to print this page.");
	}
}

window.onload = function() {
	myApp.mathTest({
		container: "math",
		difficulty: 100,
		numproblems: 100,
		columns: 0,
		questiontypes: [0, 1, 2]
	});
};