#include <stdio.h>
#include <raylib.h>
#include <cute_tiled.h>
#include <flecs.h>

#define BZ_ENTRYPOINT
#include <breeze.h>
#include "world/tileset.h"

static void drawTile(Texture2D texture, int tid, int tileSetWidth, int size, Vector2 pos) {
    Rectangle rec = {(tid % tileSetWidth) * size, (tid / tileSetWidth) * size, size, size};

    DrawTextureRec(texture, rec, pos, WHITE);
}

static void drawLayer(cute_tiled_layer_t *layer, Tileset *tileset) {
    Vector2 pos = {layer->offsetx, layer->offsety};

    for (int y = 0; y < layer->height; y++) {
        for (int x = 0; x < layer->width; x++) {
            int tile = layer->data[y * layer->width + x];
            if (tile - tileset->startID != -1) {
                Rectangle rec = tilesetGetTileRegion(tileset, tile);
                DrawTextureRec(tileset->tiles, rec, pos, WHITE);
            }
            pos.x += tileset->tileWidth;
        }
        pos.x = layer->offsetx;
        pos.y += tileset->tileHeight;
    }
}

typedef struct Game {
    cute_tiled_map_t *map;
    Camera2D camera;
    Tileset terrainTileset;
    Tileset buildingsTileset;
    cute_tiled_layer_t *terrain;
    cute_tiled_layer_t *trees;
    cute_tiled_layer_t *trees2;
    cute_tiled_layer_t *buildings;
} Game;

static Game GAME = {};

bool init(Game *game) {
    game->map = cute_tiled_load_map_from_file("assets/maps/test.tmj", NULL);
    cute_tiled_tileset_t *terrainSource = cute_tiled_load_external_tileset("assets/terrain.tsj", NULL);

    cute_tiled_tileset_t *buildingsSource = cute_tiled_load_external_tileset("assets/buildings.tsj", NULL);

    game->terrainTileset = tilesetCreate( &(TilesetDesc) {
            .source=terrainSource,
            .assetDir="assets"
    });
    game->buildingsTileset = tilesetCreate(&(TilesetDesc) {
            .source=buildingsSource,
            .assetDir="assets"
    });


    cute_tiled_tileset_t *tileset = game->map->tilesets;
    game->terrainTileset.startID = tileset->firstgid;
    tileset = tileset->next;
    game->buildingsTileset.startID = tileset->firstgid;

    cute_tiled_free_external_tileset(terrainSource);
    cute_tiled_free_external_tileset(buildingsSource);



    game->terrain = NULL;
    game->trees = NULL;
    game->trees2 = NULL;
    game->buildings = NULL;
    // loop over the map's layers
    cute_tiled_layer_t* layer = game->map->layers;
    while (layer)
    {
        int* data = layer->data;
        int data_count = layer->data_count;

        if (strcmp("Terrain", layer->name.ptr) == 0) {
            game->terrain = layer;
        } else if (strcmp("Foliage", layer->name.ptr) == 0) {

        } else if (strcmp("Trees", layer->name.ptr) == 0) {
            game->trees = layer;
        } else if (strcmp("TreesS", layer->name.ptr) == 0) {
            game->trees2 = layer;
        } else if (strcmp("Buildings", layer->name.ptr) == 0) {
            game->buildings = layer;
        }

        layer = layer->next;
    }

    int screenWidth = 1280;
    int screenHeight = 720;

    game->camera = (Camera2D){ 0 };
    game->camera.target = (Vector2) {0, 0};
    game->camera.offset = (Vector2) {screenWidth / 2.0f, screenHeight / 2.0f};
    game->camera.rotation = 0.0f;
    game->camera.zoom = 1.0f;
    return true;
}
void deinit(Game *game) {
    tilesetDestroy(&game->terrainTileset);
    tilesetDestroy(&game->buildingsTileset);
    cute_tiled_free_map(game->map);
}
void render(float dt, Game *game) {
    Camera2D *camera = &game->camera;
    if (IsKeyDown(KEY_W)) camera->target.y -= 20;
    if (IsKeyDown(KEY_S)) camera->target.y += 20;
    if (IsKeyDown(KEY_A)) camera->target.x -= 20;
    if (IsKeyDown(KEY_D)) camera->target.x += 20;

    if (IsKeyDown(KEY_Q)) camera->rotation--;
    if (IsKeyDown(KEY_E)) camera->rotation++;

    camera->zoom += ((float)GetMouseWheelMove() * 0.05f);

    BeginDrawing();
    BeginMode2D(*camera);
    ClearBackground(RAYWHITE);

    drawLayer(game->terrain, &game->terrainTileset);
    drawLayer(game->trees, &game->terrainTileset);
    drawLayer(game->trees2, &game->terrainTileset);
    drawLayer(game->buildings, &game->buildingsTileset);

    EndMode2D();
    EndDrawing();
}

bool bzMain(BzAppDesc *appDesc, int argc, const char **argv) {
    appDesc->width = 1280;
    appDesc->height = 720;
    appDesc->title = "PixelDefense";
    appDesc->fps = 60;

    appDesc->init = (BzAppInitFunc) init;
    appDesc->deinit = (BzAppDeinitFunc) deinit;
    appDesc->render = (BzAppRenderFunc) render;

    appDesc->userData = &GAME;

    return true;
}
