import { loadImage } from "@napi-rs/canvas";
import * as zlib from "node:zlib";
import * as Images from "../../common/images";

export interface Point {
	x: number;
	y: number;
}

export const VISUAL_BLOCK_SIZE = 3;

// Standard Roborock Palette (Dark Mode style)
export const ROBOROCK_PALETTE = [
	"#DFDFDFff", // 0: Default (background/no color)
	"#50A4FF", // 1: Blue
	"#FF744D", // 2: Orange
	"#008FA8", // 3: Cyan
	"#F5AF10", // 4: Yellow
	"#E9E9E9ff", // 5: Reserve/Fallback
];

// Legacy Colors used in V1 map (can be deprecated if we fully switch to Palette)
export const LEGACY_COLORS = {
	floor: "#23465e",
	obstacle: "#2b2e30",
	path: "#FFFFFF",
};

export const ALGORITHM_COLORS = {
	// Colors for the adjacency algorithm visualization if needed
	// Usually mapped to ROBOROCK_PALETTE indices
};

export async function loadSharedImages(robotType?: string) {
	let robotImgSource = Images.IMG_ROBOT_ORIGINAL;
	switch (robotType) {
		case "robot":
			robotImgSource = Images.IMG_ROBOT_DEFAULT;
			break;
		case "robot1":
			robotImgSource = Images.IMG_ROBOT1;
			break;
		case "tank":
			robotImgSource = Images.IMG_TANK;
			break;
		case "spaceship":
			robotImgSource = Images.IMG_SPACESHIP;
			break;
		case "robot2":
			robotImgSource = Images.IMG_ROBOT_2;
			break;
	}
	return Promise.all([loadImage(robotImgSource), loadImage(Images.IMG_CHARGER), loadImage(Images.IMG_GO_TO_PIN)]);
}

export function robotXtoCanvasX(x: number, left: number): number {
	return (x - left) * VISUAL_BLOCK_SIZE + VISUAL_BLOCK_SIZE / 2;
}

export function robotYtoCanvasY(y: number, top: number, height: number): number {
	return (height / VISUAL_BLOCK_SIZE + top - y) * VISUAL_BLOCK_SIZE - VISUAL_BLOCK_SIZE / 2;
}

// Convert room ID to Hex Color using standard palette
export function getRoomColor(colorId: number): string {
	if (colorId > 0 && colorId < ROBOROCK_PALETTE.length) {
		return ROBOROCK_PALETTE[colorId];
	}
	// Wrap around format for IDs larger than palette
	return ROBOROCK_PALETTE[1 + ((colorId - 1) % (ROBOROCK_PALETTE.length - 2))];
	// -2 because index 0 is bg, index 5 is fallback? Algorithm usually uses 4 colors (1-4).
	// Let's stick to 4 main colors.
}

export function hexToRgba(hex: string, alpha = 255): [number, number, number, number] {
	const r = parseInt(hex.slice(1, 3), 16);
	const g = parseInt(hex.slice(3, 5), 16);
	const b = parseInt(hex.slice(5, 7), 16);
	return [r, g, b, alpha];
}

/**
 * B01 and V1: compression is always ZLIB (0x78) or GZIP (0x1f 0x8b) at offset 0. No scan, no raw deflate.
 */
export function decompress(compressed: Buffer): Buffer {
	if (isSignatureMatch(compressed)) return compressed;
	if (compressed.length < 2) return compressed;
	if (compressed[0] === 0x78) {
		return zlib.inflateSync(compressed);
	}
	if (compressed[0] === 0x1f && compressed[1] === 0x8b) {
		return zlib.gunzipSync(compressed);
	}
	return compressed;
}

export function isSignatureMatch(buf: Buffer): boolean {
	if (buf.length < 2) return false;
	// V1: "rr"
	if (buf[0] === 0x72 && buf[1] === 0x72) return true;
	// B01: "B01"
	if (buf.length > 3 && buf.toString("ascii", 0, 3) === "B01") return true;
	// Protobuf: 0x08, 0x0a, 0x12
	return isLikelyProtobuf(buf);
}

export function isLikelyProtobuf(buf: Buffer): boolean {
	if (buf.length < 1) return false;
	return buf[0] === 0x08 || buf[0] === 0x0a || buf[0] === 0x12;
}
