// Copyright (c) 2023 Alex Diener. All rights reserved.

#include "PROJECT_NAME/Globals.h"
#include "PROJECT_NAME/RoomVisual.h"

RoomVisual * RoomVisual_create(RoomState * roomState) {
	RoomVisual * self = malloc(sizeof(*self));
	self->layers = malloc(roomState->roomData->layerCount * sizeof(*self->layers));
	self->layerCount = 0;
	for (unsigned int layerIndex = 0; layerIndex < roomState->roomData->layerCount; layerIndex++) {
		if (roomState->roomData->layers[layerIndex].type == ROOM_LAYER_TYPE_GROUND || roomState->roomData->layers[layerIndex].type == ROOM_LAYER_TYPE_OBSTACLE) {
			self->layers[self->layerCount].type = roomState->roomData->layers[layerIndex].type;
			self->layers[self->layerCount].visual = TileMapVisual_create(g_tileset, g_imageCollection);
			TileMapVisual_addTileInstanceGrid(self->layers[self->layerCount].visual, &roomState->roomData->layers[layerIndex].tileGrid, roomState->roomData->layers[layerIndex].offset);
			self->layerCount++;
		}
	}
	return self;
}

void RoomVisual_dispose(RoomVisual * self) {
	for (unsigned int layerIndex = 0; layerIndex < self->layerCount; layerIndex++) {
		TileMapVisual_dispose(self->layers[layerIndex].visual);
	}
	free(self->layers);
	free(self);
}

RoomVisual * RoomVisual_copy(RoomVisual * self) {
	RoomVisual * copy = malloc(sizeof(*copy));
	copy->layerCount = self->layerCount;
	copy->layers = malloc(self->layerCount * sizeof(*self->layers));
	for (unsigned int layerIndex = 0; layerIndex < self->layerCount; layerIndex++) {
		copy->layers[layerIndex].type = self->layers[layerIndex].type;
		copy->layers[layerIndex].visual = TileMapVisual_copy(self->layers[layerIndex].visual);
	}
	return copy;
}

void RoomVisual_draw(RoomVisual * self, Vector2f offset, VertexIO * vertexIO) {
	float drawnTileWidth = g_tileset->tileSize.x;
	float drawnTileHeight = g_tileset->tileSize.y;
	struct vertex_p2f_t2f_c4f vertices[4], vertex = {.position = {0.0f, 0.0f}, .color = {1.0f, 1.0f, 1.0f, 1.0f}};
	uint32_t indexes[6] = {0, 1, 2, 2, 3, 0};
	for (unsigned int layerIndex = 0; layerIndex < self->layerCount; layerIndex++) {
		TileMapVisual * visual = self->layers[layerIndex].visual;
		for (unsigned int drawnTileIndex = 0; drawnTileIndex < visual->drawnTileCount; drawnTileIndex++) {
			TileMapVisual_drawnTile drawnTile = visual->drawnTiles[drawnTileIndex];
			Vector2f tilePosition = VECTOR2f(offset.x + drawnTile.tilePosition.x * drawnTileWidth + drawnTile.offset.x, offset.y + TILE_MAP_HEIGHT * TILE_HEIGHT - (drawnTile.tilePosition.y * drawnTileHeight + drawnTile.offset.y));
			Rect4f tileBounds = Rect4f_fromPositionSizeOrigin(tilePosition,
			                                                  VECTOR2f(drawnTile.size.x, drawnTile.size.y),
			                                                  VECTOR2f(0.0f, 1.0f));
			vertex.position[0] = tileBounds.xMin;
			vertex.position[1] = tileBounds.yMax;
			vertex.texCoords[0] = drawnTile.textureBounds.xMin;
			vertex.texCoords[1] = drawnTile.textureBounds.yMax;
			vertices[0] = vertex;
			vertex.position[1] = tileBounds.yMin;
			vertex.texCoords[1] = drawnTile.textureBounds.yMin;
			vertices[1] = vertex;
			vertex.position[0] = tileBounds.xMax;
			vertex.texCoords[0] = drawnTile.textureBounds.xMax;
			vertices[2] = vertex;
			vertex.position[1] = tileBounds.yMax;
			vertex.texCoords[1] = drawnTile.textureBounds.yMax;
			vertices[3] = vertex;
			unsigned int vertexCount = 4, indexCount = 6;
			switch (drawnTile.shape) {
				case TILE_SHAPE_QUAD:
					break;
					
				case TILE_SHAPE_TRIANGLE_UPPER_LEFT:
					vertexCount = indexCount = 3;
					vertices[2] = vertices[3];
					break;
					
				case TILE_SHAPE_TRIANGLE_UPPER_RIGHT:
					vertexCount = indexCount = 3;
					vertices[1] = vertices[2];
					vertices[2] = vertices[3];
					break;
					
				case TILE_SHAPE_TRIANGLE_LOWER_LEFT:
					vertexCount = indexCount = 3;
					break;
					
				case TILE_SHAPE_TRIANGLE_LOWER_RIGHT:
					vertexCount = indexCount = 3;
					vertices[0] = vertices[1];
					vertices[1] = vertices[2];
					vertices[2] = vertices[3];
					break;
			}
			VertexIO_writeIndexedVertices(vertexIO, vertexCount, vertices, indexCount, indexes);
		}
	}
}
