const setMask = (state) => {
	const canvas = imageCollection.layers.mask.canvas;
	switch (state) {
		case "clear":
			canvas.classList.remove("hold");
			canvas.classList.add("display", "clear");
			break;
		case "hold":
			canvas.classList.remove("clear");
			canvas.classList.add("display", "hold");
			break;
		case "neutral":
			canvas.classList.remove("clear", "hold");
			canvas.classList.add("display");
			break;
		case "none":
			canvas.classList.remove("display", "hold", "clear");
			break;
		default:
			console.debug(`[maskbrush.setMask] Invalid mask type: ${state}`);
			break;
	}
};

const _mask_brush_draw_callback = (evn, state, opacity = 100) => {
	maskPaintCtx.globalCompositeOperation = "source-over";
	maskPaintCtx.strokeStyle = "black";

	maskPaintCtx.filter =
		"blur(" + state.brushBlur + "px) opacity(" + opacity + "%)";
	maskPaintCtx.lineWidth = state.brushSize;
	maskPaintCtx.beginPath();
	maskPaintCtx.moveTo(
		evn.px === undefined ? evn.x : evn.px,
		evn.py === undefined ? evn.y : evn.py
	);
	maskPaintCtx.lineTo(evn.x, evn.y);
	maskPaintCtx.lineJoin = maskPaintCtx.lineCap = "round";
	maskPaintCtx.stroke();
	maskPaintCtx.filter = null;
};

const _mask_brush_erase_callback = (evn, state, opacity = 100) => {
	maskPaintCtx.globalCompositeOperation = "destination-out";
	maskPaintCtx.strokeStyle = "black";

	maskPaintCtx.filter = "blur(" + state.brushBlur + "px)";
	maskPaintCtx.filter =
		"blur(" + state.brushBlur + "px) opacity(" + opacity + "%)";
	maskPaintCtx.lineWidth = state.brushSize;
	maskPaintCtx.beginPath();
	maskPaintCtx.moveTo(
		evn.px === undefined ? evn.x : evn.px,
		evn.py === undefined ? evn.y : evn.py
	);
	maskPaintCtx.lineTo(evn.x, evn.y);
	maskPaintCtx.lineJoin = maskPaintCtx.lineCap = "round";
	maskPaintCtx.stroke();
	maskPaintCtx.filter = null;
};

const maskBrushTool = () =>
	toolbar.registerTool(
		"./res/icons/paintbrush.svg",
		"Mask Brush",
		(state, opt) => {
			// Draw new cursor immediately
			uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
			state.redraw();

			// Start Listeners
			mouse.listen.world.onmousemove.on(state.movecb);
			mouse.listen.world.onwheel.on(state.wheelcb);
			mouse.listen.world.btn.left.onpaintstart.on(state.drawcb);
			mouse.listen.world.btn.left.onpaint.on(state.drawcb);
			mouse.listen.world.btn.right.onpaintstart.on(state.erasecb);
			mouse.listen.world.btn.right.onpaint.on(state.erasecb);

			// Display Mask
			setMask("neutral");
		},
		(state, opt) => {
			// Clear Listeners
			mouse.listen.world.onmousemove.clear(state.movecb);
			mouse.listen.world.onwheel.clear(state.wheelcb);
			mouse.listen.world.btn.left.onpaintstart.clear(state.drawcb);
			mouse.listen.world.btn.left.onpaint.clear(state.drawcb);
			mouse.listen.world.btn.right.onpaintstart.clear(state.erasecb);
			mouse.listen.world.btn.right.onpaint.clear(state.erasecb);

			// Hide Mask
			setMask("none");
			state.ctxmenu.previewMaskButton.classList.remove("active");
			maskPaintCanvas.classList.remove("opaque");
			state.preview = false;

			uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);
		},
		{
			init: (state) => {
				state.config = {
					brushScrollSpeed: 1 / 4,
					minBrushSize: 10,
					maxBrushSize: 500,
					minBlur: 0,
					maxBlur: 30,
				};

				state.brushSize = 64;
				state.brushBlur = 0;
				state.brushOpacity = 1;
				state.setBrushSize = (size) => {
					state.brushSize = size;
					state.ctxmenu.brushSizeRange.value = size;
					state.ctxmenu.brushSizeText.value = size;
				};

				state.preview = false;

				state.clearPrevCursor = () =>
					uiCtx.clearRect(0, 0, uiCanvas.width, uiCanvas.height);

				state.redraw = () => {
					state.movecb({
						...mouse.coords.world.pos,
						evn: {
							clientX: mouse.coords.window.pos.x,
							clientY: mouse.coords.window.pos.y,
						},
					});
				};

				state.movecb = (evn) => {
					const vcp = {x: evn.evn.clientX, y: evn.evn.clientY};
					const scp = state.brushSize * viewport.zoom;

					state.clearPrevCursor();
					state;
					clearPrevCursor = () =>
						uiCtx.clearRect(
							vcp.x - scp / 2 - 10,
							vcp.y - scp / 2 - 10,
							vcp.x + scp / 2 + 10,
							vcp.y + scp / 2 + 10
						);

					uiCtx.beginPath();
					uiCtx.arc(vcp.x, vcp.y, scp / 2, 0, 2 * Math.PI, true);
					uiCtx.strokeStyle = "black";
					uiCtx.stroke();

					uiCtx.beginPath();
					uiCtx.arc(vcp.x, vcp.y, scp / 2, 0, 2 * Math.PI, true);
					uiCtx.fillStyle = "#FFFFFF50";
					uiCtx.fill();
				};

				state.redraw = () => {
					state.movecb({
						...mouse.coords.world.pos,
						evn: {
							clientX: mouse.coords.window.pos.x,
							clientY: mouse.coords.window.pos.y,
						},
					});
				};

				state.wheelcb = (evn) => {
					if (!evn.evn.ctrlKey) {
						state.brushSize = state.setBrushSize(
							state.brushSize -
								Math.floor(state.config.brushScrollSpeed * evn.delta)
						);
						state.redraw();
					}
				};

				state.drawcb = (evn) =>
					_mask_brush_draw_callback(evn, state, state.brushOpacity * 100);
				state.erasecb = (evn) =>
					_mask_brush_erase_callback(evn, state, state.brushOpacity * 100);
			},
			populateContextMenu: (menu, state) => {
				if (!state.ctxmenu) {
					state.ctxmenu = {};

					// Brush size slider
					const brushSizeSlider = _toolbar_input.slider(
						state,
						"brushSize",
						"Brush Size",
						{
							min: state.config.minBrushSize,
							max: state.config.maxBrushSize,
							step: 5,
							textStep: 1,
							cb: (v) => {
								if (!state.cursorLayer) return;

								state.redraw();
							},
						}
					);
					state.ctxmenu.brushSizeSlider = brushSizeSlider.slider;
					state.setBrushSize = brushSizeSlider.setValue;

					// Brush opacity slider
					const brushOpacitySlider = _toolbar_input.slider(
						state,
						"brushOpacity",
						"Brush Opacity",
						{
							min: 0,
							max: 1,
							step: 0.05,
							textStep: 0.001,
						}
					);
					state.ctxmenu.brushOpacitySlider = brushOpacitySlider.slider;

					// Brush blur slider
					const brushBlurSlider = _toolbar_input.slider(
						state,
						"brushBlur",
						"Brush Blur",
						{
							min: state.config.minBlur,
							max: state.config.maxBlur,
							step: 1,
						}
					);
					state.ctxmenu.brushBlurSlider = brushBlurSlider.slider;

					// Some mask-related action buttons
					const actionArray = document.createElement("div");
					actionArray.classList.add("button-array");

					const clearMaskButton = document.createElement("button");
					clearMaskButton.classList.add("button", "tool");
					clearMaskButton.textContent = "Clear";
					clearMaskButton.title = "Clears Painted Mask";
					clearMaskButton.onclick = () => {
						maskPaintLayer.clear();
					};

					const previewMaskButton = document.createElement("button");
					previewMaskButton.classList.add("button", "tool");
					previewMaskButton.textContent = "Preview";
					previewMaskButton.title = "Displays Mask with Full Opacity";
					previewMaskButton.onclick = () => {
						if (previewMaskButton.classList.contains("active")) {
							maskPaintCanvas.classList.remove("opaque");
							state.preview = false;

							state.redraw();
						} else {
							maskPaintCanvas.classList.add("opaque");
							state.preview = true;
							state.redraw();
						}
						previewMaskButton.classList.toggle("active");
					};

					state.ctxmenu.previewMaskButton = previewMaskButton;

					actionArray.appendChild(clearMaskButton);
					actionArray.appendChild(previewMaskButton);

					state.ctxmenu.actionArray = actionArray;
				}

				menu.appendChild(state.ctxmenu.brushSizeSlider);
				menu.appendChild(state.ctxmenu.brushOpacitySlider);
				menu.appendChild(state.ctxmenu.brushBlurSlider);
				menu.appendChild(state.ctxmenu.actionArray);
			},
			shortcut: "M",
		}
	);