importScripts("seedrandom.js");
importScripts("generator.js");

let workerId;
let workerName;
let winType;
let numbers;
let batchSize;

let nameIndex = 0;
let attempts = 0;
let startedAt;

let statsInterval;
let guessInterval;

function getBoard(name) {
	Math.seedrandom(name);

	let numbers = [];

	for (let i = 0; i < 9; i++) {
		numbers = numbers.concat(generate_col(i));
	}

	const activatedCols = generate_rows_check();
	const board = [[], [], []];

	for (let row = 0; row < 3; row++) {
		for (const col of activatedCols[row]) {
			board[row].push(numbers[(col - 1) * 3 + row]);
		}
	}

	return board;
}

function hasWonRow(row, numbers) {
	return row.every(number => numbers.includes(number));
}

function getRowsWon(board, numbers) {
	return board.filter(row => hasWonRow(row, numbers)).length;
}

function hasWon(wonRows, winType) {
	switch (winType) {
		case "row":
			return wonRows >= 1;
		case "two-rows":
			return wonRows >= 2;
		case "full-board":
			return wonRows >= 3;
	}
}

function guess() {
	for (let i = 0; i < 100; i++) {
		const name = workerName + nameIndex++;
		attempts++;

		const board = getBoard(name);
		
		const wonRows = getRowsWon(board, numbers);

		if (hasWon(wonRows, winType)) {
			console.log(board, board.filter(row => hasWonRow(row, numbers)), numbers);
			self.postMessage({ type: "winner", name });
			self.postMessage({ type: "log", text: `Found winner: ${name}`, id: workerId });
		}
	}
}

function sendStats() {
	if (!startedAt) return;

	self.postMessage({ type: "stats", attempts, time: Date.now() - startedAt });
	resetStats();
}

function resetStats() {
	attempts = 0;
	startedAt = Date.now();
}

function run() {
	statsInterval = setInterval(sendStats, 1000);
	guessInterval = setInterval(guess, 0);

	resetStats();

	self.postMessage({ type: "log", text: "Starting worker", id: workerId });
}

function stop() {
	if (!statsInterval && !guessInterval) return;

	clearInterval(statsInterval);
	clearInterval(guessInterval);

	statsInterval = null;
	guessInterval = null;

	sendStats();

	self.postMessage({ type: "log", text: "Stopping worker", id: workerId });
}

self.onmessage = message => {
	switch (message.data.type) {
		case "init":
			workerId = message.data.id;
			workerName = message.data.name;
			winType = message.data.winType;
			numbers = message.data.numbers;
			batchSize = message.data.batchSize;
			self.postMessage({ type: "ready" });
			break;
		case "run":
			run();
			break;
		case "stop":
			stop();
			break;
		case "terminate":
			stop();
			self.postMessage({ type: "terminate" });
			break;
	}
};