#include <stdlib.h>

#include "../include/entity.h"
#include "../include/tile.h"
#include "../include/const.h"
#include "../include/util.h"

/* ########################################################################## */
/* # Tile                                                                   # */
/* ########################################################################## */

tile_t *tile_create(pos_t pos, tile_e type) {
  tile_t *tile = malloc(sizeof(tile_t));
  tile->pos = pos;
  tile->type = type;
  return tile;
}

void tile_update(tile_t *tile, game_t *game) {
  UNUSED(tile);
  UNUSED(game);
}

void tile_draw(tile_t *tile, game_t *game) {
  switch (tile->type) {
    case TILE_AIR: {
      break;
    }
    case TILE_STONE: {
      DrawTextureRec(game->assets.tiles, texture_rect(0, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_STONE_JOINT: {
      DrawTextureRec(game->assets.tiles, texture_rect(1, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_STONE_WALL: {
      DrawTextureRec(game->assets.tiles, texture_rect(2, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_GRASS: {
      DrawTextureRec(game->assets.tiles, texture_rect(3, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_WOOD_PLATFORM: {
      DrawTextureRec(game->assets.tiles, texture_rect(4, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_SNOW: {
      DrawTextureRec(game->assets.tiles, texture_rect(5, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_SAND: {
      DrawTextureRec(game->assets.tiles, texture_rect(6, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BOX: {
      DrawTextureRec(game->assets.tiles, texture_rect(7, 0, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_CHANDELIER: {
      DrawTextureRec(game->assets.background, texture_rect_v(3, 5, 4, 3, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_WINDOW_1: {
      DrawTextureRec(game->assets.background, texture_rect_v(8, 0, 4, 6, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_WINDOW_2: {
      DrawTextureRec(game->assets.background, texture_rect_v(8, 7, 3, 4, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_BANNER: {
      DrawTextureRec(game->assets.background, texture_rect_v(3, 0, 3, 4, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_BRICK_1: {
      DrawTextureRec(game->assets.background, texture_rect_v(0, 0, 2, 3, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_BRICK_2: {
      DrawTextureRec(game->assets.background, texture_rect_v(0, 4, 2, 1, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_BRICK_3: {
      DrawTextureRec(game->assets.background, texture_rect_v(0, 6, 2, 2, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
    case TILE_BG_INFO: {
      DrawTextureRec(game->assets.background, texture_rect_v(12, 0, 10, 6, TILE_WIDTH, TILE_HEIGHT), tile->pos, WHITE);
      break;
    }
  }
}

tile_t *tile_get(game_t *game, int x, int y) {
  for (int i = 0; i < game->tiles_len; i++) {
    tile_t *tile = game->tiles[i];
    if (x >= tile->pos.x && x <= tile->pos.x + TILE_WIDTH) {
      if (y >= tile->pos.y && y <= tile->pos.y + TILE_HEIGHT) {
        return tile;
      }
    }
  }
  return NULL;
}

bool tile_ground(tile_t *tile) {
  switch (tile->type) {
    case TILE_STONE:
    case TILE_GRASS:
    case TILE_WOOD_PLATFORM:
    case TILE_STONE_JOINT:
    case TILE_SNOW:
    case TILE_SAND:
    case TILE_BOX:
      return true;
    default:
      return false;
  }
}

bool tile_solid(tile_t *tile) {
  switch (tile->type) {
    case TILE_STONE:
    case TILE_GRASS:
    case TILE_STONE_JOINT:
    case TILE_SNOW:
    case TILE_SAND:
      return true;
    default:
      return false;
  }
}

bool tile_wall(tile_t *tile) {
  switch (tile->type) {
    case TILE_STONE_WALL:
      return true;
    default:
      return false;
  }
}

void tile_free(tile_t *tile) {
  free(tile);
}
