function getCurrentView() {
	var room = rooms.find(room => room.id == userData.position);
	displayViews(room);
}

function updateCargo() {
	let cargoContainer = document.getElementById("cargo");
	groupByType(userData.inCargoHold).forEach((group) => {
		let cargoRow = document.createElement("div");
		cargoRow.innerHTML = `${group[0].description} (x${group.length})`;
		cargoContainer.appendChild(cargoRow);
	})
}

function buildActions(room) {
	document.getElementById("additional-actions").innerHTML = "";
	if (room.actions) {
		room.actions.forEach(control => {
			let state = states.find(state => state.id == control);
			if (!state.show || state.show()) {
				let actionButton = document.createElement("button");
				actionButton.className = "action button";
				actionButton.innerHTML = state.button;
				actionButton.addEventListener("click", event => {
					trigger(state);
				});
				document.getElementById("additional-actions").appendChild(actionButton);
			}
		});
	}
}

function triggerStateById(stateId) {
	let state = states.find(state => state.id == stateId);
	trigger(state);
}

function buildDoors(room) {
	document.getElementById("destinations").innerHTML = "";
	if (room.doors) {
		room.doors.forEach(door => {
			let doorButton = document.createElement("button");
			doorButton.className = "door button";
			let doorText = document.createElement("span")
			doorText.className = "text"
			doorText.innerHTML = door.button;
			doorButton.appendChild(doorText)
			doorButton.addEventListener("click", event => {
				trigger(door);
			});
			document.getElementById("destinations").appendChild(doorButton);
		})
	}
}

function setDoorsActive(room) {
	let doorContainer = document.getElementById("destinations");
	for(let i = 0; i < doorContainer.children.length; i++) {
		let door = doorContainer.children[i];
		door.disabled = "";
		if (isFlagEnabled('solar-enabled') || isFlagEnabled('ramjet-enabled') || isFlagEnabled('ion-engine-enabled')) {
			door.disabled = "disabled";
		}
	}
}

async function displayViews(room) {
	let viewsContainer = document.getElementById('room-views');
	viewsContainer.innerHTML = "";

	play(room.play);
	await setupShipStatus(room, viewsContainer);
	for(let i = 0; i < room.viewable.length; i++) {
		let viewable = room.viewable[i];
		let template = await templateLoader.get(viewable.elementId);
		let container = document.createElement('div');
		container.id = viewable.elementId;
		container.innerHTML = template;
		viewsContainer.appendChild(container);
		setupViewable(room, viewable, container);
	}
	if(room.enter) {
		room.enter();
	}
	await setupChat(room, viewsContainer);
}
async function setupShipStatus(room, viewsContainer) {
	let template = await templateLoader.get("shipstatus")
	let container = document.createElement('div');
	container.id = "shipstatus";
	container.innerHTML = template;
	viewsContainer.appendChild(container);
	updateActivity("Idle");

	updateFuel();
	updateMoney();
	updateEnergy();
	updateCargo();
}

function setupViewable(room, viewable, element) {
	element.style.display = "block";
	switch (viewable.elementId) {
		case "put-in-inventory":
			putInInventory(viewable, element, viewable.data.source());
			break;
		case "get-from-inventory":
			getFromInventory(viewable, element, viewable.data.validator);
			break;
		case 'asteroid-field':
			updateSpaceDebris();
			break;
		case 'room-description':
			updatePosition(room.name);
			updateDescription(room.description);
			break;
		case 'doors':
			buildDoors(room);
			setDoorsActive(room);
			break;
		case 'actions':
			buildActions(room);
			break;
	}
}

async function setupChat(room, viewsContainer) {
	let template = await templateLoader.get("chat")
	let container = document.createElement('div');
	container.id = "chat";
	container.innerHTML = template;
	viewsContainer.appendChild(container);
	attachChat(room);
}

function updatePosition(newPositionText) {
    if (!newPositionText) {
        return;
    }
    document.getElementById("position").innerHTML = "Location: " + newPositionText;
}

function updateDescription(newDescriptionText) {
    if (!newDescriptionText) {
        return;
    }
    document.getElementById("description").innerHTML = newDescriptionText;
}

function putInInventory(viewable, element, gatheringSource) {
	let moveLeft = (event) => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let right = element.getElementsByClassName("right-inv-selector")[0];
		right.removeChild(event.target);
		left.appendChild(event.target);
		let index = selectedItems.indexOf(event.target.item);
		if (index > -1) {
			selectedItems.splice(index, 1);
		}
		event.target.removeEventListener("click", moveLeft);
		event.target.addEventListener("click", moveRight);
		let topBar = element.getElementsByClassName("top-bar")[0];
		let cargoSize = topBar.getElementsByTagName("span")[0];
		cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;
	};

	let moveRight = (event) => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let right = element.getElementsByClassName("right-inv-selector")[0];
		left.removeChild(event.target);
		right.appendChild(event.target);
		selectedItems.push(event.target.item);
		event.target.removeEventListener("click", moveRight);
		event.target.addEventListener("click", moveLeft);
		let topBar = element.getElementsByClassName("top-bar")[0];
		let cargoSize = topBar.getElementsByTagName("span")[0];
		cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;
	};

	selectedItems = [];
	let left = element.getElementsByClassName("left-inv-selector")[0];
	left.innerHTML = '';
	let right = element.getElementsByClassName("right-inv-selector")[0];
	right.innerHTML = '';
	gatheringSource.forEach(item => {
		let clickableItem = document.createElement("div");
		clickableItem.innerHTML = item.description;
		clickableItem.className = "clickable-inventory-item";
		clickableItem.item = item;
		clickableItem.addEventListener("click", moveRight);
		left.appendChild(clickableItem);
	});

	userData.inCargoHold.forEach(item => {
		let unclickableItem = document.createElement("div");
		unclickableItem.innerHTML = item.description;
		unclickableItem.className = "inventory-item";
		right.appendChild(unclickableItem);
	});
	let header = element.getElementsByClassName('selector-header')[0];
	header.innerHTML = viewable.data.button;
	let topBar = element.getElementsByClassName("top-bar")[0];
	let selectAll = topBar.getElementsByTagName("button")[0];
	selectAll.addEventListener("click", event => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let selectableItems = left.getElementsByClassName("clickable-inventory-item");
		for (let i = selectableItems.length - 1; i >= 0; i--) {
			let child = selectableItems[i];
			child.click();
		};
	});
	let cargoSize = topBar.getElementsByTagName("span")[0];
	cargoSize.innerHTML = `${selectedItems.length + userData.inCargoHold.length}/${userData.maxCargoCapacity}`;

	let bottomBar = element.getElementsByClassName("bottom-bar")[0];
	let actionButton = bottomBar.getElementsByTagName("button")[0];
	actionButton.innerHTML = viewable.data.button;
	actionButton.addEventListener("click", () => {
		triggerStateById(viewable.data.action);
	});
}

function getFromInventory(viewable, element, validator = () => true) {
	let moveLeft = (event) => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let right = element.getElementsByClassName("right-inv-selector")[0];
		right.removeChild(event.target);
		left.appendChild(event.target);
		let index = selectedItems.indexOf(event.target.item);
		if (index > -1) {
			selectedItems.splice(index, 1);
		}
		
		event.target.removeEventListener("click", moveLeft);
		event.target.addEventListener("click", moveRight);
	};

	let moveRight = (event) => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let right = element.getElementsByClassName("right-inv-selector")[0];
		left.removeChild(event.target);
		right.appendChild(event.target);
		selectedItems.push(event.target.item);
		event.target.removeEventListener("click", moveRight);
		event.target.addEventListener("click", moveLeft);
	};

	selectedItems = [];
	let left = element.getElementsByClassName("left-inv-selector")[0];
	left.innerHTML = '';
	let right = element.getElementsByClassName("right-inv-selector")[0];
	right.innerHTML = '';
	userData.inCargoHold.forEach(item => {
		let clickableItem = document.createElement("div");
		clickableItem.innerHTML = item.description;
		clickableItem.className = "inventory-item";
		if(validator(item)) {
			clickableItem.className = "clickable-inventory-item";
		}
		clickableItem.item = item;
		clickableItem.addEventListener("click", moveRight);
		left.appendChild(clickableItem);
	});

	let header = element.getElementsByClassName('selector-header')[0];
	header.innerHTML = viewable.data.button;
	let topBar = element.getElementsByClassName("top-bar")[0];
	let selectAll = topBar.getElementsByTagName("button")[0];
	selectAll.addEventListener("click", event => {
		let left = element.getElementsByClassName("left-inv-selector")[0];
		let selectableItems = left.getElementsByClassName("clickable-inventory-item");
		for (let i = selectableItems.length - 1; i >= 0; i--) {
			let child = selectableItems[i];
			child.click();
		};
	});

	let bottomBar = element.getElementsByClassName("bottom-bar")[0];
	let actionButton = bottomBar.getElementsByTagName("button")[0];
	actionButton.innerHTML = viewable.data.button;
	actionButton.addEventListener("click", () => {
		if(viewable.data.action) {
			triggerStateById(viewable.data.action);
		}
	});
}

function updateSpaceDebris() {
	let debrisContainer = document.getElementById("asteroid-field");
	groupByType(userData.debrisInSpace).forEach((group) => {
		let debrisRow = document.createElement("div");
		debrisRow.innerHTML = `${group[0].description} (x${group.length})`;
		debrisContainer.appendChild(debrisRow);
	})
}

function trigger(control) {
	clearTimeout(timeoutId);
	document.getElementById("progress").value = 0;
	errorMessage = "";
	if (control.requires()) {
		// disableAction();
		updateActivity(control.action);
		startControl(control);

		let step = control.step || 10;
		if (typeof control.step == "function") {
			step = control.step();
		}

		let duration = control.duration;
		if (typeof control.duration == "function") {
			duration = control.duration();
		}
		if (duration > 0) {
			delayLoop(() => runControl(control), duration, step);
		} else {
			runControl(control);
		}
	}
	updateError();
}

function startControl(control) {
	if(control.start) {
		control.start();
	}
}

function runControl(control) {
	control.run();
	save();
	// enableAction();
	getCurrentView();
}

function save() {
	localStorage.setItem("spaceloop1-save", JSON.stringify(userData));
}

function load() {
	var gameDataString = localStorage.getItem("spaceloop1-save");
	if (gameDataString == null) {
		// No save file! let's start at the beginning.
		getCurrentView();
		return;
	}
	userData = JSON.parse(gameDataString);
	migrateVersion(userData);
	getCurrentView();
}
function migrateVersion(oldUserData) {
	//TODO: check save file version, adjust as needed
}

function setFlag(flag) {
	if (!userData.enabled.find(enabledFlag => enabledFlag == flag)) {
		userData.enabled.push(flag);
	}
}

function clearFlag(flag) {
	let index = userData.enabled.findIndex(enabledFlag => enabledFlag == flag);
	if (index != -1) {
		userData.enabled.splice(index, 1);
	}
}

function isFlagEnabled(flag) {
	return !!userData.enabled.find(enabledFlag => enabledFlag == flag);
}