//This file contains the information about the puzzle (network)
//Each puzzle is stored in the allpuzzles variable.  We need to select one and use it

//We define this here, even though it is used primarily in the UI.  We define its values here
var ui_helplevel = 0;


var puzzle=networkFromName("Level0-Ping");
//var puzzle=networkFromName("Level0-NeedsLink");
//var puzzle=networkFromName("Level0_NetworkLoop");
//var puzzle=networkFromName("Level0_NetworkLoop2");
//var puzzle=networkFromName("Level0-SimpleDHCP");
//console.log(puzzle.name);

var device=deviceFromName("laptop0");
if(device !== null)  {console.log("We found laptop0");}
else { console.log("Seems to be null"); }

function switchPuzzle(target)
{
	var newpuzzle=null;
	if(typeof(target)==="string") newpuzzle = networkFromName(target);
	if(typeof(target)==="number") newpuzzle = networkFromIndex(target);
	if(newpuzzle!= null)
	{
		puzzle = newpuzzle;
		PrintScreen();
	}
}

function networkFromName(what)
{
	let index=0;
	while (index < allpuzzles.length) {
	//console.log(allpuzzles[index].EduNetworkBuilder.Network.name);
	if(allpuzzles[index].EduNetworkBuilder.Network.name == what)
	{
		console.log("Found " + what + " at index " + index);
		return networkFromIndex(index);
	}
	index++;
	}
}
function networkFromIndex(what)
{
	if(typeof(what)==="number" && what >= 0 && what < allpuzzles.length){		
		var newitem = structuredClone(allpuzzles[what].EduNetworkBuilder.Network);
		console.log("It is an array:" + Array.isArray(newitem.nettest));
		if (!Array.isArray(newitem.nettest)) {
			var oneitem = newitem.nettest; //this is an object
			newitem.nettest = [];
			newitem.nettest.push(oneitem); //make it an one-item array.
        }

		//Set the help level to be whatever we need
		if (newitem.startinghelplevel == "full") ui_helplevel = 3;
		if (newitem.startinghelplevel == "hints") ui_helplevel = 2;
		if (newitem.startinghelplevel == "basic") ui_helplevel = 1;
		if (newitem.startinghelplevel == "none") ui_helplevel = 0;

		console.log("Starting help level = " + ui_helplevel + " from " + newitem.startinghelplevel);

		return newitem;
	}
	return null;
}

function deviceHasProblem(Device) {
	var hostname = Device.hostname;
	//console.log("Looking for tests on " + hostname + " and have: " + puzzle.nettest.length)
	for (var index = 0; index < puzzle.nettest.length; index++) {
		//console.log("Found test: " + JSON.stringify(puzzle.nettest));
		if (puzzle.nettest[index].shost == hostname) {
			if (puzzle.nettest[index].solved == null) {
				//It has not yet been solved.
				//console.log("Found problem on device: " + hostname);
				return true;
            }
        }
	}
	return false;
}

function networkNamesMatchingText(textToMatch)
{
	var list = [];
	var re = new RegExp(textToMatch);

	let index=0;
	while (index < allpuzzles.length) {
		//console.log(allpuzzles[index].EduNetworkBuilder.Network.name);
		if(re.test(allpuzzles[index].EduNetworkBuilder.Network.name))
		{
			//console.log("Found " + textToMatch + " at index " + index + "  " + allpuzzles[index].EduNetworkBuilder.Network.name);
			list.push(allpuzzles[index].EduNetworkBuilder.Network.name);
		}
		index++;
	}
	return list;
}

function deviceFromName(what)
{
	if (puzzle == null) return null; //If the puzzle has not been set, return a null

	let index=0;
	while (index < puzzle.device.length) {
	if (puzzle.device[index].hostname == what) return puzzle.device[index]; //return the device that matches
	index++;
	}
	return null; //No match.  return a null value
}

function deviceFromID(what)
{
	if (puzzle == null) return null; //If the puzzle has not been set, return a null

	let index=0;
	while (index < puzzle.device.length) {
	if (puzzle.device[index].uniqueidentifier == what) return puzzle.device[index]; //return the device that matches
	index++;
	}
	return null; //No match.  return a null value
}

//return a list of all the ip addresses a device has
function ipsFromDevice(what) {
	var ipaddresses = [];
	for (var i = 0; i < what.nic.length; i++) {
		ipaddresses = ipaddresses.concat(ipsFromNic(what.nic[i]));
	}
	//console.log("Adding to nics " + ipaddresses.length);
	return ipaddresses;
}

function ipsFromInterface(what, nictype) {
	var ipaddresses = [];
	if (typeof (what.myip) === "array") {
		for (var x = 0; x < what.myip.length; x++) {
			var one = {
				nic: what.nicname,
				ip: what.myip[x].ip,
				mask: what.myip[x].mask,
				cidrip: what.myip[x].ip + "/" + NetmaskToCIDR(what.myip[x].mask),
				nictype: nictype,
			};
			ipaddresses.push(one);
		}
	}
	else if (typeof (what.myip) === "object") {
		var one = {
			nic: what.nicname,
			ip: what.myip.ip,
			mask: what.myip.mask,
			cidrip: what.myip.ip + "/" + NetmaskToCIDR(what.myip.mask),
			nictype: nictype,
		};
		ipaddresses.push(one);
		//console.log("found an ip object: " + JSON.stringify(one) + "  " + nictype);
	}
	return ipaddresses;
}

function ipsFromNic(what) {
	var ipaddresses = [];
	//console.log("Looking at a nic: " + JSON.stringify(what));
	if (typeof (what.interface) === "array") {
		for (var i = 0; i < what.interface.length; i++) {
			//console.log("Trying to add a nic." + what.interface[i].nicname);
			ipaddresses=ipaddresses.concat(ipsFromInterface(what.interface[i],what.nictype[0]));
		}
	}
	else if (typeof (what.interface) === "object")
		ipaddresses=ipaddresses.concat(ipsFromInterface(what.interface, what.nictype[0]));

	return ipaddresses;
}

function NetmaskToCIDR(mask) {
	var cidr = 0;
	var maskNodes = mask.match(/(\d+)/g);
	for (var i in maskNodes) {
		cidr += (((maskNodes[i] >>> 0).toString(2)).match(/1/g) || []).length;
	}
	return cidr;
}