var controllerTypes = [
	"desktop",
	"mobile",
	"console"
];

class Controller {
	constructor (type, options = {}) {
		if (controllerTypes.indexOf(type) < 0) return new Error(
			"Controller type must be \"desktop\", \"mobile\" or \"console\". "
		);
		this.type = type;

		this.mappings = {};
		this.actions = {};

		switch (this.type) {
			case "desktop":
				if (options.domElement) {
					this.domElement = options.domElement;
				} else {
					this.domElement = document.querySelector(":root");
				}
				break;
			case "mobile":
				if (options.domElements) {
					this.domElements = options.domElements;
				} else {
					this.domElements = {
						"main": document.querySelector(":root")
					};
				}
				break;
			case "console":
				if (!options.gamepad) return new Error("A gamepad object must be passed. ");
				this.gamepad = options.gamepad;
				break;
			default:
				return null;
		}
	}
	registerMapping (mapping, action) {
		this.mappings[mapping] = action;
	}
	registerAction (action, callback) {
		this.actions[action] = callback;
	}
	unregisterMapping (mapping) {
		delete this.mappings[mapping];
	}
	unregisterAction (action) {
		delete this.actions[action];
	}
	grab () {
		switch (this.type) {
			case "desktop":
				this.domElement.requestPointerLock();

				this.domElement.onkeyup = this.domElement.onkeydown = processKeyEvent.bind(this);

				this.domElement.onmousemove = this.domElement.onmousedown = this.domElement.onmouseup = processMouseEvent.bind(this);
				break;
			default:

		}
	}
	release () {
		switch (this.type) {
			case "desktop":
				document.exitPointerLock();

				this.domElement.onkeyup = this.domElement.onkeydown = null;

				this.domElement.onmousemove = null;
				this.domElement.onmousedown = this.domElement.onmouseup = null;
				break;
			default:

		}
	}
}

var processKeyEvent = function (event) {
	var mapping = this.mappings[event.code];
	if (!mapping) return;

	let eventType;

	switch (event.type) {
		case "keydown":
			eventType = "down";
			break;
		case "keyup":
			eventType = "up";
			break;
		default:

	}

	var action = this.actions[mapping];
	if (typeof action == "function") action(eventType);
};

var processMouseEvent = function (event) {
	let eventType;
	let mappingName;
	let movement;

	switch (eventType) {
		case "mousedown":
			eventType = "down";
			mappingName = "MouseDown" + event.which;
			break;
		case "mousemove":
			eventType = "move";
			mappingName = "MouseMove";

			movement = [event.movementX, event.movementY];
			break;
		case "mouseup":
			eventType = "up";
			mappingName = "MouseUp" + event.which;
			break;
		default:

	}

	var mapping = this.mappings[mappingName];
	if (!mapping) return;

	var action = this.actions[mapping];
	if (typeof action == "function") action(((eventType == "move") ? movement : eventType));
};

module.exports = {
	"Controller": Controller
};

global.core.on("pre-init", function () {
	global.core.emit("input-init");
});
