import { WindowMouseEvent } from "https://deno.land/x/dwm@0.3.3/mod.ts";
import { gameWindow } from "./window.ts";

export const M = {
	NONE: -1,
	LEFT: 0,
	RIGHT: 1,
	MIDDLE: 2,
}

const mouseButtonsDown = {
	[M.LEFT]: false,
	[M.RIGHT]: false,
	[M.MIDDLE]: false,
};

type MouseEventType = "click" | "down" | "up" | "move" | "dblclick";

const mouseEvents: Array<{
	type: MouseEventType,
	button: typeof M[keyof typeof M],
	x: number,
	y: number,
	prevX?: number,
	prevY?: number
}> = [];

let mouseX = 0;
let mouseY = 0;

const eventPixelCoords = (evt: WindowMouseEvent) => {
	const {width, height} = gameWindow.size;
	const min = Math.min(width, height);
	const pixX = Math.floor(128*(evt.clientX-(width-min)/2)/min);
	const pixY = Math.floor(128*(evt.clientY-(height-min)/2)/min);
	if (pixX < 0 || pixX > 128 || pixY < 0 || pixY > 128) {
		return null;
	}
	return {
		x: pixX,
		y: pixY,
	}
}

const pushEvent = (type: MouseEventType, evt: WindowMouseEvent, extra?: Partial<typeof mouseEvents[0]>) => {
	const coords = eventPixelCoords(evt);
	if (!coords) {
		return
	}
	mouseEvents.push({type, button: evt.button, ...coords, ...(extra ?? {})});
}

const evtInBounds = (evt: WindowMouseEvent) => {
	return !!eventPixelCoords(evt);
}

addEventListener("dblclick", (evt) => {
	pushEvent("dblclick", evt);
});

addEventListener("click", (evt) => {
	pushEvent("click", evt);
});

addEventListener("mousedown", (evt) => {
	if (evtInBounds(evt)) {
		mouseButtonsDown[evt.button] = true;
	}
	pushEvent("down", evt);
});

addEventListener("mouseup", (evt) => {
	if (evtInBounds(evt)) {
		mouseButtonsDown[evt.button] = false;
	}
	pushEvent("up", evt);
});

addEventListener("mousemove", (evt) => {
	const coords = eventPixelCoords(evt);
	pushEvent("up", evt, {prevX: mouseX, prevY: mouseY});
	if (coords) {
		mouseX = coords.x;
		mouseY = coords.y;
	}
});

export const mousePos = () => {
	return {
		x: mouseX,
		y: mouseY,
	}
}

export const getMouseX = () => {
	return mouseX;
}

export const getMouseY = () => {
	return mouseY;
}

export const refreshMouse = () => {
	mouseEvents.length = 0;
}

export const mouseDown = (button: number = M.LEFT) => {
	return mouseEvents.some(ev => ev.button === button && ev.type === "down");
}

export const mouseClick = (button: number = M.LEFT) => {
	return mouseEvents.some(ev => ev.button === button && ev.type === "click");
}

export const mouseDoubleClick = (button: number = M.LEFT) => {
	return mouseEvents.some(ev => ev.button === button && ev.type === "dblclick");
}

export const mouseHeld = (button: number = M.LEFT) => {
	return mouseButtonsDown[button];
}