'use strict';

const { PNG } = require('pngjs');

// Minecraft map color palette (base colors × 4 shades each)
// Source: https://minecraft.wiki/w/Map_item_format#Color_table
// Index 0-3 = NONE (transparent), 4-7 = GRASS, 8-11 = SAND, etc.
// Each base color has 4 multipliers: 0.71, 0.86, 1.0, 0.53
const BASE_COLORS = [
	null,                // 0: NONE
	[127, 178, 56],      // 1: GRASS
	[247, 233, 163],     // 2: SAND
	[199, 199, 199],     // 3: WOOL
	[255, 0, 0],         // 4: FIRE
	[160, 160, 255],     // 5: ICE
	[167, 167, 167],     // 6: METAL
	[0, 124, 0],         // 7: PLANT
	[255, 255, 255],     // 8: SNOW
	[164, 168, 184],     // 9: CLAY
	[151, 109, 77],      // 10: DIRT
	[112, 112, 112],     // 11: STONE
	[64, 64, 255],       // 12: WATER
	[143, 119, 72],      // 13: WOOD
	[255, 252, 245],     // 14: QUARTZ
	[216, 127, 51],      // 15: COLOR_ORANGE
	[178, 76, 216],      // 16: COLOR_MAGENTA
	[102, 153, 216],     // 17: COLOR_LIGHT_BLUE
	[229, 229, 51],      // 18: COLOR_YELLOW
	[127, 204, 25],      // 19: COLOR_LIGHT_GREEN
	[242, 127, 165],     // 20: COLOR_PINK
	[76, 76, 76],        // 21: COLOR_GRAY
	[153, 153, 153],     // 22: COLOR_LIGHT_GRAY
	[76, 127, 153],      // 23: COLOR_CYAN
	[127, 63, 178],      // 24: COLOR_PURPLE
	[51, 76, 178],       // 25: COLOR_BLUE
	[102, 76, 51],       // 26: COLOR_BROWN
	[102, 127, 51],      // 27: COLOR_GREEN
	[153, 51, 51],       // 28: COLOR_RED
	[25, 25, 25],        // 29: COLOR_BLACK
	[250, 238, 77],      // 30: GOLD
	[92, 219, 213],      // 31: DIAMOND
	[74, 128, 255],      // 32: LAPIS
	[0, 217, 58],        // 33: EMERALD
	[129, 86, 49],       // 34: PODZOL
	[112, 2, 0],         // 35: NETHER
	[209, 177, 161],     // 36: TERRACOTTA_WHITE
	[159, 82, 36],       // 37: TERRACOTTA_ORANGE
	[149, 87, 108],      // 38: TERRACOTTA_MAGENTA
	[112, 108, 138],     // 39: TERRACOTTA_LIGHT_BLUE
	[186, 133, 36],      // 40: TERRACOTTA_YELLOW
	[103, 117, 53],      // 41: TERRACOTTA_LIGHT_GREEN
	[160, 77, 78],       // 42: TERRACOTTA_PINK
	[57, 41, 35],        // 43: TERRACOTTA_GRAY
	[135, 107, 98],      // 44: TERRACOTTA_LIGHT_GRAY
	[87, 92, 92],        // 45: TERRACOTTA_CYAN
	[122, 73, 88],       // 46: TERRACOTTA_PURPLE
	[76, 62, 92],        // 47: TERRACOTTA_BLUE
	[76, 50, 35],        // 48: TERRACOTTA_BROWN
	[76, 82, 42],        // 49: TERRACOTTA_GREEN
	[142, 60, 46],       // 50: TERRACOTTA_RED
	[37, 22, 16],        // 51: TERRACOTTA_BLACK
	[189, 48, 49],       // 52: CRIMSON_NYLIUM
	[148, 63, 97],       // 53: CRIMSON_STEM
	[92, 25, 29],        // 54: CRIMSON_HYPHAE
	[22, 126, 134],      // 55: WARPED_NYLIUM
	[58, 142, 140],      // 56: WARPED_STEM
	[86, 44, 62],        // 57: WARPED_HYPHAE
	[20, 180, 133],      // 58: WARPED_WART_BLOCK
	[100, 100, 100],     // 59: DEEPSLATE
	[216, 175, 147],     // 60: RAW_IRON
	[127, 167, 150],     // 61: GLOW_LICHEN
];

const SHADE_MULTIPLIERS = [180, 220, 255, 135]; // out of 255

// Build the full 256-entry lookup: MAP_COLORS[colorIndex] → [r, g, b]
const MAP_COLORS = new Array(256).fill(null);
for (let base = 0; base < BASE_COLORS.length; base++) {
	for (let shade = 0; shade < 4; shade++) {
		const idx = base * 4 + shade;
		if (!BASE_COLORS[base]) {
			MAP_COLORS[idx] = [0, 0, 0, 0]; // transparent
		} else {
			const [r, g, b] = BASE_COLORS[base];
			const m = SHADE_MULTIPLIERS[shade];
			MAP_COLORS[idx] = [
				Math.floor(r * m / 255),
				Math.floor(g * m / 255),
				Math.floor(b * m / 255),
				255
			];
		}
	}
}

/**
 * Apply a partial map update from a protocol packet to a pixel buffer.
 * @param {Uint8Array} pixels - 128×128 color index buffer (mutated in place)
 * @param {Object} packet - Map protocol packet with columns, rows, x, y, data
 */
function applyMapUpdate(pixels, packet) {
	const { columns, rows, x, y, data } = packet;
	if (!columns || columns === 0 || !data) return;

	for (let col = 0; col < columns; col++) {
		for (let row = 0; row < rows; row++) {
			const srcIdx = col * rows + row;
			const dstX = x + col;
			const dstY = y + row;
			if (dstX < 128 && dstY < 128) {
				pixels[dstY * 128 + dstX] = data[srcIdx];
			}
		}
	}
}

/**
 * Render a 128×128 color-index buffer to a base64 PNG string.
 * @param {Uint8Array} pixels - 128×128 array of Minecraft color indices
 * @returns {string} base64-encoded PNG
 */
function renderMapToPNG(pixels) {
	const png = new PNG({ width: 128, height: 128 });

	for (let i = 0; i < 128 * 128; i++) {
		const colorIdx = pixels[i];
		const color = MAP_COLORS[colorIdx] || [0, 0, 0, 0];
		const offset = i * 4;
		png.data[offset] = color[0];     // R
		png.data[offset + 1] = color[1]; // G
		png.data[offset + 2] = color[2]; // B
		png.data[offset + 3] = color[3]; // A
	}

	const buffer = PNG.sync.write(png);
	return buffer.toString('base64');
}

module.exports = { MAP_COLORS, applyMapUpdate, renderMapToPNG };
