import { clearScreen, fillRect } from "./window.ts";
import { drawSprite, drawText } from "./builtins.ts";
import { COLOR } from "./colors.ts";
import { getMapSheet, getSheet, setSheet } from "./sheet.ts";
import { M, mouseClick, mouseDown, mouseHeld, mousePos } from "./mouse.ts";
import { drawTransparentRect, drawVoidRect, inRect, reGrid } from "./util.ts";
import { page } from "./viewsheets.ts";
import { useSpritesheet } from "./builtins.ts";
import { keyPressed } from "./keyboard.ts";
import { K } from "./keyboard.ts";

const state = {
	selectedSpriteSheet: 0,
	selectedSprite: 0,
	viewX: 0,
	viewY: 0,
	dragging: false,
	dragFromViewX: 0,
	dragFromViewY: 0,
	dragFromX: 0,
	dragFromY: 0,
	get spriteSheetPage() {
		return Math.floor(this.selectedSprite/64);
	},
	set spriteSheetPage(val) {
		this.selectedSprite = 64*val+this.spriteWithinPage;
	},
	get spriteWithinPage() {
		return this.selectedSprite%64;
	},
	set spriteWithinPage(val) {
		this.selectedSprite = 64*this.spriteSheetPage+val;
	},
	get map() {
		return getMapSheet(page.activeSheet);
	},
	set map(val) {
		setSheet(page.activeSheet, "map", val);
	},
	setInPatch(i: number, sprsheet: number, sprite: number) {
		const cellVal = this.map.subgrid(this.viewX, this.viewY, patchW, patchH).values[i];
		if (cellVal) {
			cellVal[0] = sprsheet
			cellVal[1] = sprite;
		}
	},
	get patch() {
		return this.map.subgrid(this.viewX, this.viewY, patchW, patchH);
	}
}

const patchX = 0;
const patchY = 8;
const patchW = 16;
const patchH = 9;

const spriteW = 8;
const spriteH = 8;

const spriteSheetX = 0;
const spriteSheetY = 88;
const spriteSheetW = 16;
const spriteSheetH = 4;

const spriteSheetPickerX = 0;
const spriteSheetPickerY = 81;
const spriteSheetPickerW = 16;
const spriteSheetPickerH = 1;
const spriteSheetPickerTabW = 7;
const spriteSheetPickerTabH = 7;

const spriteSheetPageSwapX = 121;
const spriteSheetPageSwapY = 81;
const spriteSheetPageSwapW = 7;
const spriteSheetPageSwapH = 7;

const update = () => {
	const {x: mouseX, y: mouseY} = mousePos();
	const inPatch = inRect(mouseX, mouseY, patchX, patchY, patchW*spriteW, patchH*spriteH - 2);
	const inSpriteSheetPicker = inRect(mouseX, mouseY, spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerW*spriteSheetPickerTabW, spriteSheetPickerH*spriteSheetPickerTabH);
	const inSpriteSheet = inRect(mouseX, mouseY, spriteSheetX, spriteSheetY, spriteSheetW*spriteW, spriteSheetH*spriteH);
	const inSpriteSheetPageSwap = inRect(mouseX, mouseY, spriteSheetPageSwapX, spriteSheetPageSwapY, spriteSheetPageSwapW, spriteSheetPageSwapH);
	if (mouseHeld()) {
		if (inPatch) {
			const {x, y} = reGrid(mouseX, mouseY, patchX, patchY, spriteW, spriteH);
			const cellNumber = patchW*y+x;
			state.setInPatch(cellNumber, state.selectedSpriteSheet, state.selectedSprite);
		}
		if (inSpriteSheetPicker) {
			const {x, y} = reGrid(mouseX, mouseY, spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerTabW, spriteSheetPickerTabH);
			state.selectedSpriteSheet = spriteSheetPickerW*y+x;
		}
		if (inSpriteSheet) {
			const {x, y} = reGrid(mouseX, mouseY, spriteSheetX, spriteSheetY, spriteW, spriteH);
			state.spriteWithinPage = spriteSheetW*y+x;
		}
	} else if (mouseDown(M.MIDDLE)) {
		if (inPatch) {
			const {x, y} = reGrid(mouseX, mouseY, patchX, patchY, spriteW, spriteH);
			state.dragging = true;
			state.dragFromX = x;
			state.dragFromY = y;
			state.dragFromViewX = state.viewX;
			state.dragFromViewY = state.viewY;
		}
	} else if (mouseHeld(M.MIDDLE)) {
		if (state.dragging) {
			const {x, y} = reGrid(mouseX, mouseY, patchX, patchY, spriteW, spriteH);
			state.viewX = state.dragFromViewX - x + state.dragFromX;
			state.viewY = state.dragFromViewY - y + state.dragFromY;
		}
	} else if (mouseClick(M.MIDDLE)) {
		state.dragging = false;
	} else if (mouseClick()) {
		if (inSpriteSheetPageSwap) {
			state.spriteSheetPage = (1+state.spriteSheetPage)%2;
		}
	}
	if (keyPressed(K.ARROW_RIGHT)) {
		state.viewX += 1;
	}
	if (keyPressed(K.ARROW_LEFT)) {
		state.viewX -= 1;
	}
	if (keyPressed(K.ARROW_UP)) {
		state.viewY -= 1;
	}
	if (keyPressed(K.ARROW_DOWN)) {
		state.viewY += 1;
	}
}

const outlineRect = (x: number, y: number, w: number, h: number, color: number) => {
	fillRect(x, y, w, 1, color);
	fillRect(x, y, 1, h, color);
	fillRect(x+w-1, y, 1, h, color);
	fillRect(x, y+h-1, w, 1, color);
}

const draw = () => {
	const {
		selectedSpriteSheet,
		spriteWithinPage,
		spriteSheetPage,
	} = state;
	clearScreen();
	fillRect(0, 8, 128, 112, COLOR.DARKGRAY);

	// Draw the current patch
	drawVoidRect(patchX-1, patchY-1, (patchW*spriteW)+2, (patchH*spriteH)+2);
	state.patch.values.forEach((val, i) => {
		const spriteX = patchX+spriteW*(i%patchW);
		const spriteY = patchY+spriteH*Math.floor(i/patchW);
		if (!val) {
			return;
		}
		const [sprsheet, sprite] = val;
		drawTransparentRect(spriteX, spriteY, 8, 8);
		if (getSheet(sprsheet).sheet_type === "spritesheet") {
			useSpritesheet(sprsheet);
			drawSprite(spriteX, spriteY, sprite);
		}
	});

	// Draw the bar
	fillRect(spriteSheetPickerX, spriteSheetPickerY-1, 128, 1, COLOR.BLACK);
	fillRect(spriteSheetPickerX, spriteSheetPickerY, 128, 7, COLOR.DARKGRAY);

	// Draw the spritesheet picker
	fillRect(spriteSheetPickerX, spriteSheetPickerY, spriteSheetPickerTabW*spriteSheetPickerW, spriteSheetPickerTabW, COLOR.BLACK);
	Array(spriteSheetPickerW*spriteSheetPickerH).fill(0).forEach((_, i) => {
		const tabX = spriteSheetPickerX+spriteSheetPickerTabW*(i%spriteSheetPickerW);
		const tabY = spriteSheetPickerY+spriteSheetPickerTabH*Math.floor(i/spriteSheetPickerW);
		let color = COLOR.DARKGREEN;
		if (getSheet(i).sheet_type !== "spritesheet") {
			color = COLOR.BROWN;
		}
		if (i === page.activeSheet) {
			color = COLOR.PURPLE;
		}
		if (i === selectedSpriteSheet) {
			color = {
				[COLOR.BROWN]: COLOR.TAN,
				[COLOR.DARKGREEN]: COLOR.GREEN,
				[COLOR.PURPLE]: COLOR.PINK,
			}[color];
		}
		fillRect(tabX, tabY, spriteSheetPickerTabW, spriteSheetPickerTabH, color);
		drawText(tabX+2, tabY+1, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"][i]);
	});

	// Draw the spritesheet page swap button
	fillRect(spriteSheetPageSwapX, spriteSheetPageSwapY, spriteSheetPageSwapW, spriteSheetPageSwapH, COLOR.BLUE);
	drawText(spriteSheetPageSwapX+2, spriteSheetPageSwapY+1, state.spriteSheetPage.toString());
	
	// Draw the spritesheet
	fillRect(spriteSheetX, spriteSheetY, (spriteSheetW*spriteW), (spriteSheetH*spriteH), COLOR.BLACK);
	if (getSheet(selectedSpriteSheet).sheet_type === "spritesheet") {
		useSpritesheet(selectedSpriteSheet);
		Array(64).fill(0).forEach((_, i) => {
			const sprI = i+64*spriteSheetPage;
			const sprX = spriteSheetX+spriteW*(i%spriteSheetW);
			const sprY = spriteSheetY+spriteH*Math.floor(i/spriteSheetW);
			drawSprite(sprX, sprY, sprI);
			if (i === spriteWithinPage) {
				outlineRect(sprX, sprY, spriteW, spriteH, COLOR.WHITE);
			}
		});
	}
}

export const maptab = {
	update,
	draw,
}