//--STRIP
#include "render_objects/tile_map.h"

#include "render_objects/camera_2d.h"
//--STRIP

void TileMap::build_mesh() {
	if (!mesh.is_valid()) {
		mesh = Ref<Mesh>(memnew(Mesh(2)));
	} else {
		mesh->clear();
	}

	if (!data) {
		//mesh->upload();

		return;
	}

	float asx = 1.0 / atlas_size_x;
	float asy = 1.0 / atlas_size_y;

	for (int x = 0; x < size_x; ++x) {
		int x_offset = x * size_x;

		for (int y = 0; y < size_y; ++y) {
			uint8_t d = data[x_offset + y];

			if (d == 0) {
				continue;
			}

			float px;
			float py;

			switch (d) {
				case 1:
					px = 1;
					py = 0;
					break;
				case 2:
					px = 0;
					py = 1;
					break;
			}

			px /= atlas_size_x;
			py /= atlas_size_y;

			add_rect(x, y, px, py, asx, asy);
		}
	}

	mesh->upload();
}

void TileMap::allocate_data() {
	if (size_x <= 0 || size_y <= 0) {
		return;
	}

	if (data) {
		memdelete_arr(data);
	}

	int size = size_x * size_y;

	data = memnew_arr(uint8_t, size);

	for (int i = 0; i < size; ++i) {
		data[i] = 0;
	}
}

void TileMap::add_rect(const int x, const int y, const float uv_x, const float uv_y, const float uv_size_x, const float uv_size_y) {
	int vc = static_cast<int>(mesh->vertices.size() / mesh->vertex_dimesions);

	mesh->add_vertex2(x, y + 1);
	mesh->add_uv(uv_x, uv_y + uv_size_y);

	mesh->add_vertex2(x + 1, y);
	mesh->add_uv(uv_x + uv_size_x, uv_y);

	mesh->add_vertex2(x, y);
	mesh->add_uv(uv_x, uv_y);

	mesh->add_vertex2(x + 1, y + 1);
	mesh->add_uv(uv_x + uv_size_x, uv_y + uv_size_y);

	mesh->add_triangle(vc + 1, vc + 0, vc + 2);
	mesh->add_triangle(vc + 0, vc + 1, vc + 3);
}

uint8_t TileMap::get_data(const int x, const int y) const {
	//3d-ben: data[(x * size_x * size_x) + (y * size_y) + size_z] etc

	return data[x * size_x + y];
}

void TileMap::set_data(const int x, const int y, const uint8_t value) {
	data[x * size_x + y] = value;
}

void TileMap::render() {
	if (!mesh.is_valid()) {
		return;
	}

	Transform2D mat_orig = Camera2D::current_camera->get_model_view_matrix();

	Camera2D::current_camera->set_model_view_matrix(mat_orig * transform);

	if (material.is_valid()) {
		material->bind();
	}

	mesh->render();

	Camera2D::current_camera->set_model_view_matrix(mat_orig);
}

TileMap::TileMap() {
	data = NULL;
	size_x = 16;
	size_y = 16;

	atlas_size_x = 1;
	atlas_size_y = 1;
}
TileMap::~TileMap() {
	if (data) {
		memdelete_arr(data);
	}
}
