// RFB holds the API to connect and communicate with a VNC server
import RFB from '/noVNC-1.3.0/core/rfb.js';

let rfb;
let desktopName;
let sessionID=0;
let connected=false;

// When this function is called we have
// successfully connected to a server
function connectedToServer(e) {
	status("Connected to " + desktopName);
	connected=true;
	document.getElementById("connectButton").classList.add("disabled");
	document.getElementById("sendCtrlAltDelButton").classList.remove("disabled");
	document.getElementById("disconnectButton").classList.remove("disabled");
}

// This function is called when we are disconnected
function disconnectedFromServer(e) {
	if (e.detail.clean) {
		status("Disconnected");
	} else {
		status("Something went wrong, connection is closed");
	}
	sessionID=0;
	connected=false;
	document.getElementById("connectButton").classList.remove("disabled");
	document.getElementById("sendCtrlAltDelButton").classList.add("disabled");
	document.getElementById("disconnectButton").classList.add("disabled");
}

// When this function is called, the server requires
// credentials to authenticate
function credentialsAreRequired(e) {
	document.getElementById("passwordPrompt").classList.remove("hidden");
	document.getElementById("password").focus();
}

// Send the vnc password to the server from the password prompt screen
function sendPassword() {
	document.getElementById("passwordPrompt").classList.add("hidden");
	const password = document.getElementById("password").value;
	rfb.sendCredentials({ password: password });
}

// When this function is called we have received
// a desktop name from the server
function updateDesktopName(e) {
	desktopName = e.detail.name;
}

// Since most operating systems will catch Ctrl+Alt+Del
// before they get a chance to be intercepted by the browser,
// we provide a way to emulate this key sequence.
function sendCtrlAltDel() {
	if(!connected) return;
	rfb.sendCtrlAltDel();
}

// Show a status text in the top bar
function status(text) {
	document.getElementById('status').textContent = text;
}


//////////////////////
// Add Event Listeners
//////////////////////
document.getElementById("passwordEnter").onclick = sendPassword;
document.getElementById("password").addEventListener("keypress", function(event) {
	if (event.key === "Enter") {
		event.preventDefault();
		sendPassword();
	}
});

document.getElementById('sendCtrlAltDelButton').onclick = sendCtrlAltDel;

document.getElementById('connectButton').onclick = getSession;

document.getElementById('disconnectButton').onclick = disconnect;

addEventListener('beforeunload', function () {
	disconnect();
});

// Once a session id is received, this handles connecting to the websocket proxy
function connect(session) {
	const host = window.location.hostname;
	let port = 6080 + session;
	const path = 'websockify';
	
	status("Connecting");
	
	// Build the websocket URL used to connect
	let url;
	if (window.location.protocol === "https:") {
		url = 'wss';
	} else {
		url = 'ws';
	}
	url += '://' + host;
	if(port) {
		url += ':' + port;
	}
	url += '/' + path;
	
	// Creating a new RFB object will start a new connection
	rfb = new RFB(document.getElementById('screen'), url, {
		wsProtocols: ['binary', 'base64']
	});
	
	// Add listeners to important events from the RFB module
	rfb.addEventListener("connect",  connectedToServer);
	rfb.addEventListener("disconnect", disconnectedFromServer);
	rfb.addEventListener("credentialsrequired", credentialsAreRequired);
	rfb.addEventListener("desktopname", updateDesktopName);
}

// Ask the server to start a new vncserver and websocket proxy for us
async function getSession() {
	if (sessionID > 0) return;
	if (connected) return;
	status("Requesting Session");
	let response = await fetch("/rest/session/new?", {
		method: "GET"
	});
	if (response.ok) {
		sessionID = Number(await response.text());
		if (sessionID) {
			connect(sessionID);
		}
	} else {
		console.warn(response.status);
	}
}

// Ask the server to terminate a vncserver and corresponding websocket proxy
async function disconnect() {
	if (!connected) return;
	let response = await fetch(`/rest/session/close?id=${sessionID}`, {
		method: "GET",
		keepalive: true
	});
	if (!response.ok) {
		console.warn(response.status);
	}
	sessionID = 0;
}
