test('[lesson.next] correct, two in a row, found, then found', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("0");
	
	//set a test array on the lesson
	var array_setup = require('lib/lesson/util/array_setup');
	var array = array_setup({size:4, fill:[0, 1, 2, 3]});
	
	//remove the array the lesson allocates automatically
	ui.stage.del(l._array);
	
	//substitute the array we allocated into the lesson
	l._array = array;
	l._arrow = array._.arrow;
	
	//add the test array to the stage
	ui.stage.add(l._array);
	
	//TEST
	
	var found_case1_interval_ID = setInterval(found_case1, 1500);
	var found_case2_interval_ID;
	
	function found_case1() {
		var result = l.next();
		
		if (result.done) {
			var output = ui.output.get();
			t.ok(output.match(/smaller/));
			t.ok(output.match(/removing the selected value/));
			
			//CLEANUP
			clearInterval(found_case1_interval_ID);
			
			//setup new input for next part of the lesson
			ui.input.set("2");
			
			found_case2_interval_ID = setInterval(found_case2, 1500);
		}
	};
	
	function found_case2() {
		var result = l.next();
		
		if (result.done) {
			console.log("DONE");
			
			var output = ui.output.get();
			t.ok(output.match(/smaller/));
			t.ok(output.match(/removing the selected value/));
			
			//CLEANUP
			TEARDOWN();
			t.end();
			clearInterval(found_case2_interval_ID);
		}
	};
});
test('[lesson] correct', function (t) {
	t.plan(4);
	//SETUP
	var ui = SETUP();
	var stage_add_called = false;
	ui.stage.add = function() {
		stage_add_called = true;
	};
	var l = lesson({UI: ui});
	
	//TEST
	t.ok(check.object(l._array), "setup the array");
	t.ok(check.object(l._arrow), "populated the arrow reference, from setting up the array");
	t.ok(stage_add_called, "added the array to the stage");
	//t.ok(check.object(l._search), "setup the search logic");
	
	//avoid calling _next() on click
	l._next = function() {};
	
	ui.pub_sub.subscribe("click.next_button", function() {
		t.ok(true, "saw click event published");
		
		TEARDOWN();
	});
	ui.pub_sub.publish("click.next_button");
});
test('[lesson.next] incorrect, INIT state', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	l._state = l._INIT;
	
	//TEST
	var result = l.next();
	
	t.notOk(result);
	
	//CLEANUP
	TEARDOWN();
	t.end();
});
test('[lesson.next] correct, search found case, looping through delete', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("0");
	
	//set a test array on the lesson
	var array_setup = require('lib/lesson/util/array_setup');
	var array = array_setup({size:4, fill:[0, 1, 2, 3]});
	
	//remove the array the lesson allocates automatically
	ui.stage.del(l._array);
	
	//substitute the array we allocated into the lesson
	l._array = array;
	l._arrow = array._.arrow;
	
	//add the test array to the stage
	ui.stage.add(l._array);
	
	//TEST
	
	//iterate through the lesson logic, until we reach the end of the search
	var intervalID = setInterval(function() {
		var result = l.next();
		
		if (result.done) {
			console.log("DONE");
			
			t.ok(check.undefined(l._delete));
			t.ok(check.undefined(l._delete_index));
			t.ok(check.undefined(l._step_state));
			t.ok(check.undefined(l._input_tmp));
			t.equal(l._state, l._READY);
			t.notOk(ui.input.self._.htmlElement.disabled, "text input is no longer disabled");
			
			var output = ui.output.get();
			t.ok(output.match(/smaller/));
			t.ok(output.match(/removing the selected value/));
			
			//CLEANUP
			TEARDOWN();
			t.end();
			clearInterval(intervalID);
		}
	}, 1500);
});
test('[lesson.next] correct, search found case (stopping before delete)', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("0");
	
	//set a test array on the lesson
	var array_setup = require('lib/lesson/util/array_setup');
	var array = array_setup({size:4, fill:[0, 1, 2, 3]});
	
	//remove the array the lesson allocates automatically
	ui.stage.del(l._array);
	
	//substitute the array we allocated into the lesson
	l._array = array;
	l._arrow = array._.arrow;
	
	//add the test array to the stage
	ui.stage.add(l._array);
	
	//TEST
	
	//iterate through the lesson logic, until we reach the end of the search
	var intervalID = setInterval(function() {
		var result = l.next();
		
		if (l._step_state === l._STEP_DELETE) {
			console.log("DONE");
			
			t.ok(check.undefined(l._search));
			t.ok(check.number(l._delete_index));
			t.equal(l._delete_index, 0);
			t.equal(l._step_state, l._STEP_DELETE);
			t.ok(check.not.undefined(l._delete));
			
			var output = ui.output.get();
			t.ok(output.match(/found the value/));
			t.ok(output.match(/remove the value/));
			
			//CLEANUP
			TEARDOWN();
			t.end();
			clearInterval(intervalID);
		}
	}, 1500);
});
test('[lesson.next] correct', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("0");
	
	//TEST
	var result = l.next();
	
	t.ok(check.object(result));
	t.notOk(result.done);
	t.ok(ui.input.self._.htmlElement.disabled, "text input disabled once started a lesson");
	
	//CLEANUP
	TEARDOWN();
	t.end();
});
test('[lesson] incorrect, no arguments', function (t) {
	t.plan(4);
	
	//SETUP
	var ui = SETUP();
	
	//TEST
	try {
		lesson();
	} catch(error) {
		t.ok(check.instanceStrict(error, TypeError), 'we should get back a TypeError');
		var message = error.toString();
		t.ok(message.match(/UI/), 'tells you what caused the problem');
		t.ok(message.match(/is required/), 'tells you what caused the problem');
		t.ok(message.match(/should be object/), 'tells you what caused the problem');
	}
	
	TEARDOWN();
});
test('[lesson.next] incorrect, bad input', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("");
	
	//TEST
	var result = l.next();
	
	t.notOk(result);
	var output = ui.output.get();
	t.ok(output.match(/not a number/), 'shows what was wrong');
	t.ok(output.match(/Please enter a number/), 'tells you what to enter');
	t.ok(output.match(/the 'Next' button/), '...and what to do');
	
	//CLEANUP
	TEARDOWN();
	t.end();
});
test('[lesson.next] _STEP_INIT_SEARCH', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("0");
	l._state = l._READY;
	
	//TEST
	var result = l.next();
	
	var output = ui.output.get();
	t.ok(output.match(/search/));
	t.ok(output.match(/linear search/));
	t.ok(output.match(/delete/));
	
	t.equal(l._step_state, l._STEP_SEARCH);
	
	//CLEANUP
	TEARDOWN();
	t.end();
});
test('[lesson.next] correct, two in a row, not found, then found', function (t) {
	//SETUP
	var ui = SETUP();
	var l = lesson({UI: ui});
	ui.input.set("-1");
	
	//set a test array on the lesson
	var array_setup = require('lib/lesson/util/array_setup');
	var array = array_setup({size:4, fill:[0, 1, 2, 3]});
	
	//remove the array the lesson allocates automatically
	ui.stage.del(l._array);
	
	//substitute the array we allocated into the lesson
	l._array = array;
	l._arrow = array._.arrow;
	
	//add the test array to the stage
	ui.stage.add(l._array);
	
	//TEST
	
	var not_found_case_interval_ID = setInterval(not_found_case, 1500);
	var found_case_interval_ID;
	
	function not_found_case() {
		var result = l.next();
		
		if (result.done) {
			t.ok(check.undefined(l._step_state));
			t.equal(l._state, l._READY, "in READY state after completely traversing a lesson");
			t.notOk(ui.input.self._.htmlElement.disabled, "text input is no longer disabled");
			t.ok(result.done);
			t.ok(check.undefined(l._search));
			
			//CLEANUP
			clearInterval(not_found_case_interval_ID);
			
			//setup new input for next part of the lesson
			ui.input.set("0");
			
			found_case_interval_ID = setInterval(found_case, 1500);
		}
	};
	
	function found_case() {
		var result = l.next();
		
		if (result.done) {
			console.log("DONE");
			
			t.ok(check.undefined(l._delete));
			t.ok(check.undefined(l._delete_index));
			t.ok(check.undefined(l._step_state));
			t.ok(check.undefined(l._input_tmp));
			t.equal(l._state, l._READY);
			t.notOk(ui.input.self._.htmlElement.disabled, "text input is no longer disabled");
			
			var output = ui.output.get();
			t.ok(output.match(/smaller/));
			t.ok(output.match(/removing the selected value/));
			
			//CLEANUP
			TEARDOWN();
			t.end();
			clearInterval(found_case_interval_ID);
		}
	};
});