// HTML for this example:


function compare(a/*: number*/, b/*: number*/)/*: ['compare', number, number]*/ {
	return ['compare', a, b];
}
function swap(a/*: number*/, b/*: number*/)/*: ['swap', number, number]*/ {
	return ['swap', a, b];
}

function* bubbleSort(from/*: number*/, to/*: number*/)/*: Generator<['swap' | 'compare', number, number], void, number> */ {
	let swapped/*: boolean */;
	do {
		swapped = false;
		to -= 1; // decrement by 1 EACH loop, as we know the last element will be in place
		for (let j = from; j < to; j++) {
			if ((yield compare(j, j + 1)) > 0) {
				yield swap(j, j + 1);
				swapped = true;
			}
		}
	} while(swapped);
}

function log(text/*: string*/)/*: void */ {
	console.log(text);
	document.getElementById('output').innerText += text + '\n';
}

function test(array/*: number[] */)/*: void */ {
	const generator = bubbleSort(0, array.length);
	let latestArray = array;
	let nextValue = 0;
	while(true) {
		const action = generator.next(nextValue);
		if(action.done) {
			log(JSON.stringify(latestArray) + ': Done')
			return;
		} else if (action.value[0] === 'compare') {
			const a = latestArray[action.value[1]];
			const b = latestArray[action.value[2]];
			if(a > b) {
				nextValue = 1;
			} else if (a < b) {
				nextValue = -1;
			} else {
				nextValue = 0;
			}
			log(JSON.stringify(latestArray) + `: Compared ${action.value[1]}: ${a} to ${action.value[2]}: ${b} resulting in ${nextValue}`);
		} else if (action.value[0] === 'swap') {
			latestArray = [...latestArray]
			const tmp = latestArray[action.value[1]];
			latestArray[action.value[1]] = latestArray[action.value[2]];
			latestArray[action.value[2]] = tmp;
			log(JSON.stringify(latestArray) + `: Swapped index ${action.value[1]} and ${action.value[2]}`);
		} else {
			throw new Error('What? ' + JSON.stringify(action.value));
		}
	}
}
const array = [9, 3, 4, 0, 7, 5, 2, 8, 1, 6];
test(array);