import { pecBoard, pec } from './pecslib.js';

// gui object classes?
// Why am I doing this?
class auxillery_dialog {
	constructor (title) {
		var me = this;
		this.root = document.createElement("div");
		this.root.classList.add("dialog");
		this.title = "string" == typeof title ? title : "";
		var title_bar = document.createElement("div");
		title_bar.classList.add("title_bar");
		var titleText = document.createElement("span");
		titleText.innerText = this.title;
		titleText.classList.add("title_text");
		title_bar.appendChild(titleText);
		this.root.appendChild(title_bar);
		this.body = document.createElement("div");
		this.root.appendChild(me.body);
		var close = document.createElement("span");
		close.innerText = "<";
		close.classList.add("close");
		title_bar.appendChild(close);
		close.addEventListener("click", ()=>{
			me.root.classList.remove("focused");
		});
	}
}

// Functions

function systemMsg (message,level=0) { // abstraction?
	// Yes, but it allows us to easilly redirect error
	// output to where we want, for now, just the console...
	switch (level) {
		case 0:
			console.log("INFO: "+message);
			break;
		case 1:
			console.error("WARNING: "+message);
			break;
		case 2:
			console.error("ERROR: "+message);
			break;
		case 3: 
			console.log("DEBUG: "+message);
			break;
		default:
			console.log(message);
	} 
	// but later we will also have it push an error toast in the ui.
}

function toggleDarkmode () {
	var html = document.documentElement;
	if (html.classList.contains("darkmode")) {
		html.classList.remove("darkmode");
	} else {
		html.classList.add("darkmode");
	}
}

function inRange(target,min,max) {
	if (isNaN(target) || isNaN(min) || isNaN(max)) { return false; }
	return (min <= target && target <= max);
}

function invokeLibrary(e) {
	// Breaking this out of event so its not an
	// annon function, so we can swap it in and out
	var targetID = ((e.currentTarget.getAttribute("id")).split("pec"))[1];
	if (isNaN(targetID)) { return systemMsg("invokeLibrary targetID not a number",2); }
	var targetPec = app.gui["pec"+targetID];
	if (undefined == targetPec) { return systemMsg("invokeLibrary targetPec undefined: "+targetID,2); }
	if (!inRange(targetID,0,15)) { return systemMsg("invokeLibrary targetID out of range: "+targetPecIndex,2); }
	app.targetPec = targetPec;
	app.targetPecIndex = targetID;
	app.gui.library.root.classList.add("focused");
}

function clearPec (index=null) {
	if (!inRange(index,0,15)) { return systemMsg("clearPec was given an out of range index",2); }
	var targetPec = app.gui["pec"+index];
	if (undefined == targetPec) { return systemMsg("clearPec targetPec undefined",2); }
	targetPec.classList.add("empty");
	targetPec.innerHTML = "<p>+</p>";
	targetPec.addEventListener("click", invokeLibrary);
}

function setPec(pecTemplate=null, targetIndex=null) {
	if (null == pecTemplate) { return systemMsg("setPec was not provided data",2); }
	if (!(pecTemplate instanceof pec)) { return systemMsg("setPec was not provided a valid template",2); }
	if (isNaN(targetIndex)) { return systemMsg("setPec was not provided a valid targetIndex",2); }
	var targetPec = app.gui["pec"+targetIndex];
	targetPec.removeEventListener("click", invokeLibrary);
	targetPec.innerHTML = "";
	targetPec.classList.remove("empty");
	var freshPec = new pec(pecTemplate.word, pecTemplate.image);
	targetPec.appendChild(freshPec.DOM);
}

function repopBoards (current=0) {
	//app.boards;
	//app.currentBoards;
	//app.menu;
	// Normally we only want <, but we want an extra
	// iteration here for the "add new board" element
	for (var i = 0; i <= app.boards.length; i++) {
		var boardTab = document.getElementById("board"+i);
		if (null == boardTab) {
			boardTab = document.createElement("span");
			boardTab.setAttribute("id", "board"+i);
			boardTab.classList.add("board_tab");
			app.gui.menu.appendChild(boardTab);
		}
		// Clear event listeners
		var oldTab = boardTab;
		boardTab = oldTab.cloneNode(true);
		oldTab.parentNode.replaceChild(boardTab, oldTab);
		// not sure how memory safe the above lines are
		var name = "Board "+i;
		if (i == app.boards.length) {
			name = "+";
			boardTab.addEventListener("click",(e)=>{
				var current = app.boards.findIndex(i=>i==app.currentBoard);
				app.boards.push(new pecBoard());
				repopBoards(current);
				repopGrid(app.currentBoard);
			});
		} else {
			if (current != i) {
				boardTab.classList.remove("active_board");
				boardTab.addEventListener("click", (e)=>{
					var sourceID = ((e.currentTarget.getAttribute("id")).split("board"))[1];
					app.currentBoard = app.boards[sourceID];
					repopBoards(sourceID);
					repopGrid(app.currentBoard);
				});
			} else {
				boardTab.classList.add("active_board");
			}
			if (undefined != app.boards[i].name) {
				name = app.boards[i].name;
			}
		}
		boardTab.innerText = name;
	}
}

function repopGrid (board=null) {
	if (null == board) { return systemMsg("repopGrid was not provided data",2); }
	if (!(board instanceof pecBoard)) { return systemMsg("repopGrid was not provided data of type pecBoard",2); }
	board.pecs.forEach((p,i)=>{
		if (null == p) { return clearPec(i); }
		if (!(p instanceof pec)) { 
			systemMsg("Invalid Pec found, scrubbing and returning to null",1);
			board.pecs[i] = null; 
			return clearPec(i); 
		}
		setPec(p,i);
	});
}

function useThisPec (e) {
	var sourceID = ((e.currentTarget.getAttribute("id")).split("lPec"))[1];
	app.gui.library.root.classList.remove("focused");
	app.currentBoard.pecs[app.targetPecIndex] = app.library.splice(sourceID,1)[0];
	repopLibrary();
	repopGrid(app.currentBoard);
}

function createNewPec () {
	var name = app.gui.newpec_name.value;
	var image = app.gui.newpec_image.files[0];
	app.library.push(new pec(name, URL.createObjectURL(image)));
	repopLibrary();
	app.gui.newpec.root.classList.remove("focused");
}

function updatePreview () {
	var name = app.gui.newpec_name.value;
	var image = app.gui.newpec_image.files[0];
	app.gui.newpec_preview.innerHTML = "";
	app.gui.newpec_preview.removeEventListener("click", createNewPec);
	app.gui.newpec_status.innerText = "Create your new pec by naming it and providing an image.";
	var correct = 0;
	if (["image/png","image/jpeg","image/svg"].includes(image?.type)) {
		var imageBox = document.createElement("img");
		imageBox.src = URL.createObjectURL(image);
		imageBox.classList.add("pecImage");
		app.gui.newpec_preview.appendChild(imageBox);
		correct++;
	}
	if ("" != name) {
		var nameBox = document.createElement("div");
		nameBox.innerText = name;
		nameBox.classList.add("pecName");
		app.gui.newpec_preview.appendChild(nameBox);
		correct++;
	}
	if (1 < correct) {
		app.gui.newpec_status.innerText = "Click/Tap the preview to save.";
		app.gui.newpec_preview.addEventListener("click", createNewPec);
	}
}

function addNewPec (e) {
	// clear out any previous values in form.
	app.gui.newpec_form.reset();
	updatePreview();
	// make form visible
	app.gui.newpec.root.classList.add("focused");
}

function repopLibrary () {
	// clear library
	app.gui.library.body.innerHTML = "";
	// recreate items from app.library
	app.library.forEach((p,i)=>{
		var newPec = document.createElement("span");
		newPec.classList.add("libSlot");
		newPec.innerText = p.word;
		newPec.id = "lPec"+i;
		newPec.addEventListener("click", useThisPec);
		app.gui.library.body.appendChild(newPec);
	});
	// add new pec button at end of list
	var newPec = document.createElement("span");
	newPec.classList.add("libSlot");
	newPec.innerText = " + ";
	newPec.id = "lPec"+(app.library.length + 1);
	newPec.addEventListener("click", addNewPec);
	app.gui.library.body.appendChild(newPec);	
}

// Initialize gui

window.app = {};
app.gui = {};
app.gui.main = document.createElement("div");
app.gui.main.id = "root";
document.body.appendChild(app.gui.main);
app.gui.menu = document.createElement("nav");
app.gui.menu.id = "navigation";
app.gui.main.appendChild(app.gui.menu);
app.gui.optionsButton = document.createElement("div");
app.gui.optionsButton.classList.add("options_button");
app.gui.optionsButton.innerHTML = "&#x2630;";
app.gui.menu.appendChild(app.gui.optionsButton);
app.gui.view = document.createElement("div");
app.gui.view.id = "view";
app.gui.main.appendChild(app.gui.view);
// Library popup
app.gui.library = new auxillery_dialog("Library");
app.gui.library.body.classList.add("library_body");
app.gui.main.append(app.gui.library.root);
// Options popup
app.gui.options = new auxillery_dialog("Options");
app.gui.options.body.classList.add("options_body");
app.gui.main.append(app.gui.options.root);
app.gui.optionsButton.addEventListener("click", ()=>{ app.gui.options.root.classList.add("focused") });
// New Pec popup
app.gui.newpec = new auxillery_dialog("Create New Pec");
app.gui.newpec.body.classList.add("newpec_body");
app.gui.main.append(app.gui.newpec.root);
// pre-populate grid with emptys
for (var x = 0; x < 16; x++) {
	var name = "pec"+x;
	var thisPec = document.createElement("span");
	app.gui[name] = thisPec;
	thisPec.classList.add("pecSlot");
	thisPec.id = name;
	clearPec(x);
	app.gui.view.appendChild(thisPec);
}
// Create our initial board
app.boards = [];
app.boards.push(new pecBoard());
app.currentBoard = app.boards[0];
repopBoards(0);
repopGrid(app.currentBoard);

// Populate Library
import { library as library } from './library.js';
app.library = library;
repopLibrary();

// Populate Options
app.options = {};
app.options.darkmode = false; // should always be an option
app.options.audioFeedback = false; // read word aloude
app.options.feedbackFloodLimit = 3;
app.options.feedbackTimeout = 60; // 60 seconds
// overload defaults with options stored in localstorage

// build Options UI
app.gui.options_darkmode = document.createElement("div");
app.gui.options.body.appendChild(app.gui.options_darkmode);
app.gui.options_darkmode.innerHTML = '<label for="darkmode-checkbox">Darkmode</label> <input id="darkmode-checkbox" type="checkbox" class="dm-indicator" />';
app.gui.options_darkmode.addEventListener("change", toggleDarkmode);

app.gui.options_audioFeedback = document.createElement("div");
app.gui.options.body.appendChild(app.gui.options_audioFeedback);
app.gui.options_audioFeedback.innerHTML = '<label for="audio-feedback-toggle">Read Allowed</label> <input id="audio-feedback-toggle" type="checkbox" class="toggle-switch" />';

app.gui.options_feedbackFloodLimit = document.createElement("div");
app.gui.options.body.appendChild(app.gui.options_feedbackFloodLimit);
app.gui.options_feedbackFloodLimit.innerHTML = '<label for="flood-limit">Audio Flood Limit</label> <input id="flood-limit" type="number" min=1 step=2 max=10 />';

app.gui.options_feedbackTimeout = document.createElement("div");
app.gui.options.body.appendChild(app.gui.options_feedbackTimeout);
app.gui.options_feedbackTimeout.innerHTML = '<label for="flood-timeout">Audio Flood Timeout</label> <input id="flood-timeout" type="number" min=0 step=10 />';

app.gui.options_about = document.createElement("div");
app.gui.options.body.appendChild(app.gui.options_about);
app.gui.options_about.innerHTML = 'App licenced <a href="LICENSE.txt" target="_blank"><img src="images/ui/gplv3-or-later.svg" height="30px" /></a><label>-</label> Cards from <a href="https://assistivecards.com" target="_blank"><img src="images/ui/ac.svg" height="30px" alt="Assistive Cards" /></a><label>-</label> Project Source <a href="https://labs.murkfall.net/bluesaxman/librePECS">labs.murkfall.net</a>';

app.gui.newpec.body.innerHTML = '<form id="new-pec-form"><label for="new-pec-name">Name</label><input id="new-pec-name" type="text" value=""  /><br /><label for="new-pec-image">Picture</label><input id="new-pec-image" type="file" accept="image/png, image/jpeg, image/svg" value="" /><br /><div id="new-pec-preview"></div><br /><div id="new-pec-status">Create your new pec by naming it and providing an image.</div></form>';
app.gui.newpec_form = document.getElementById("new-pec-form");
app.gui.newpec_name = document.getElementById("new-pec-name");
app.gui.newpec_image = document.getElementById("new-pec-image");
app.gui.newpec_preview = document.getElementById("new-pec-preview");
app.gui.newpec_status = document.getElementById("new-pec-status");
app.gui.newpec_preview.classList.add("pecSlot");
app.gui.newpec_name.addEventListener("change", updatePreview);
app.gui.newpec_image.addEventListener("change", updatePreview);

