import standard;
import node;

//consts
var TILE_WIDTH: int const = 32;
var TILE_HEIGHT: int const = 32;


//vars
var mapWidth: int = 0;
var mapHeight: int = 0;

//map between the identity and position on the sprite sheet
var rawmap: [[string]] = null;

var tilemap: [int] = null; // [x0, y0, x1, y1, ...]
var collisions: [bool] = null;

var tileset: [string : [int]] = [
	"pillar": [0, 0, 0],
	
	"floor-0": [0, 1, 1],
	"floor-1": [1, 1, 1],
	"floor-2": [2, 1, 1],
	"floor-3": [3, 1, 1],

	"wall-t": [0, 2, 0],
	"wall-b": [1, 2, 0],
	"wall-l": [2, 2, 0],
	"wall-r": [3, 2, 0],

	"corner-tl": [0, 3, 0],
	"corner-tr": [1, 3, 0],
	"corner-bl": [2, 3, 0],
	"corner-br": [3, 3, 0],

	"edge-tl": [0, 4, 0],
	"edge-tr": [1, 4, 0],
	"edge-bl": [2, 4, 0],
	"edge-br": [3, 4, 0]
];


//debug vars
var camX = 0;
var camY = 0;
var camW = 1080;
var camH = 720;


//lifecycle functions
fn onLoad(node: opaque) {
	node.loadTexture("sprites:/tileset.png");
}

fn customOnDraw(node: opaque) {
	if (tilemap == null) {
		return;
	}

	//calc the region to render
	var lowerX: int = round((camX - camW/2.0) / TILE_WIDTH);
	var upperX: int = round((camX - camW*1.5) / TILE_WIDTH);
	var lowerY: int = round((camY - camH/2.0) / TILE_HEIGHT);
	var upperY: int = round((camY - camH*1.5) / TILE_HEIGHT);

	//bounds check
	lowerX = max(0, lowerX);
	upperX = min(upperX < 0 ? abs(upperX) : 0, mapWidth);
	lowerY = max(0, lowerY);
	upperY = min(upperY < 0 ? abs(upperY) : 0, mapHeight);

	var runner: int = 0;

	//draw the tilemap
	for (var j = lowerY; j < upperY; j++) {
		for (var i = lowerX; i < upperX; i++) {
			node.setNodeRect(tilemap[j * mapWidth * 2 + i * 2] * 16, tilemap[j * mapWidth * 2 + i * 2 + 1] * 16, 16, 16);

			node.drawNode(i * TILE_WIDTH, j * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
		}
	}
}


//utils functions for map generation
fn generateFromRng(node: opaque, rng: opaque, width: int, height: int) {
	rawmap = generateRawTilemap(rng, width, height);

	tilemap = bakeTilemap(rawmap, width, height);
	collisions = bakeCollisionMap(rawmap, width, height);

	mapWidth = width;
	mapHeight = height;

	print tilemap;
	print collisions;
}

fn generateRawTilemap(rng: opaque, width: int, height: int) {
	import random;

	//generate an empty grid
	var result: [[string]] = [];
	var row: [string] = [];
	for (var j: int = 0; j < height; j++) {
		row.push("pillar");
	}

	for (var i: int = 0; i < width; i++) {
		result.push(row);
	}

	//generate the contents of the grid - floor
	for (var j: int = 1; j < height - 1; j++) {
		for (var i: int = 1; i < width - 1; i++) {
			//select a random floor tile
			var x: int = rng.generateRandomNumber() % 4;
			var t: string = "floor-" + string x;

			result[i][j] = t;
		}
	}

	//draw top and bottom walls
	for (var i: int = 1; i < width - 1; i++) {
		result[i][0] = "wall-t";
		result[i][height - 1] = "wall-b";
	}

	//draw the left and right walls
	for (var j: int = 1; j < height - 1; j++) {
		result[0][j] = "wall-l";
		result[width-1][j] = "wall-r";
	}

	//draw the corners
	result[0][0] = "corner-tl";
	result[width - 1][0] = "corner-tr";
	result[0][height - 1] = "corner-bl";
	result[width - 1][height - 1] = "corner-br";

	//debug
	result[4][4] = "pillar";
	result[width - 5][4] = "pillar";
	result[4][height - 5] = "pillar";
	result[width - 5][height - 5] = "pillar";

	return result;
}

fn bakeCollisionMap(tilemap: [[string]], width: int, height: int) {
	//generate an empty grid
	var result: [bool] = [];

	//extract the collision map
	for (var j: int = 0; j < height; j++) {
		for (var i: int = 0; i < width; i++) {
			//almost - you still need one pair of parentheses
			result.push(tileset[ tilemap[i][j] ][2] != 0);
		}
	}
	
	return result;
}

fn bakeTilemap(tilemap: [[string]], width: int, height: int) {
	//generate an empty grid
	var result: [int] = [];

	//extract the position map
	for (var j: int = 0; j < height; j++) {
		for (var i: int = 0; i < width; i++) {
			result.push(tileset[ tilemap[i][j] ][0]);
			result.push(tileset[ tilemap[i][j] ][1]);
		}
	}
	
	return result;
}

fn getCollisionMap(node: opaque) {
	return collisions;
}