#include "assets.hpp"
#include "config.hpp"
#include "state.hpp"
#include "texture.hpp"
#include <SDL.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <map.hpp>

std::vector<std::string> split(std::string s, std::string delimiter) {
  size_t pos_start = 0, pos_end, delim_len = delimiter.length();
  std::string token;
  std::vector<std::string> res;

  while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
    token = s.substr(pos_start, pos_end - pos_start);
    pos_start = pos_end + delim_len;
    res.push_back(token);
  }

  res.push_back(s.substr(pos_start));
  return res;
}

Map PLoadMapFromFile(std::string filepath) {
  SDL_Log("Loading map from: %s", filepath.c_str());

  Map map{};

  std::ifstream mapFile(filepath);

  std::string mapFileLine;

  while (std::getline(mapFile, mapFileLine)) {
    std::vector<std::string> mapCommand = split(mapFileLine, " ");

    if (mapCommand[0] == "MAPNAME") {
      map.mapName = mapCommand[1];
    } else if (mapCommand[0] == "MAPVERS") {
      map.mapVersion = mapCommand[1];
    } else if (mapCommand[0] == "MAPAUTH") {
      map.mapAuthor = mapCommand[1];
    } else if (mapCommand[0] == "MAPSIZE") {
      std::vector<std::string> mapSize = split(mapCommand[1], "x");
      map.mapWidth = std::stoi(mapSize[0]);
      map.mapHeight = std::stoi(mapSize[1]);
    } else if (mapCommand[0] == "MAP") {
    } else if (mapCommand[0] == "ENEMYS") {
    } else if (mapCommand[0] == "TILE") {
      map.data.mapTiles.push_back(mapCommand[1]);
    } else if (mapCommand[0] == "ENEMY") {
      map.data.mapEnemys.push_back(mapCommand[1]);
    } else if (mapCommand[0] == "MAPSCAL") {
      std::vector<std::string> mapScale = split(mapCommand[1], "x");
      map.mapScaleX = std::stoi(mapScale[0]);
      map.mapScaleY = std::stoi(mapScale[1]);
    }
  }

  SDL_Log("Map info:");

  SDL_Log("Map name: %s", map.mapName.c_str());
  SDL_Log("Map author: %s", map.mapAuthor.c_str());
  SDL_Log("Map version: %s", map.mapVersion.c_str());

  SDL_Log("Map size: %ix%i", map.mapWidth, map.mapHeight);

  SDL_Log("Map tile count: %s",
          std::to_string(map.data.mapTiles.size()).c_str());

  SDL_Log("Map enemy count: %s",
          std::to_string(map.data.mapEnemys.size()).c_str());

  return map;
}

void PRenderMap(Map *map) {

  PhoenixTexture *brickWallTexture = PGetTextureById(BRICK_WALL_TEXTURE_ID);
  PhoenixTexture *floorTexture = PGetTextureById(FLOOR_TEXTURE_ID);

  int i = 0;
  int row = 0;
  for (auto tileName : map->data.mapTiles) {
    if (i + 1 > map->mapWidth) {
      row++;
      i = 0;
    }

    int x = i * TEXTURE_WIDTH;
    int y = row * TEXTURE_HEIGHT;

    if (tileName == "WALL") {
      PRenderTexture(brickWallTexture, x, y);
    } else if (tileName == "FLOOR") {
      PRenderTexture(floorTexture, x, y);
    }

    i++;
  }
}

void PSaveMapToFile(Map *map, std::string filepath) {
  std::string mapContent;
  mapContent += "MAPNAME " + map->mapName + "\n";
  mapContent += "MAPVERS " + map->mapVersion + "\n";
  mapContent += "MAPAUTH " + map->mapAuthor + "\n";
  mapContent += "MAPSIZE " + std::to_string(map->mapWidth) + "x" +
                std::to_string(map->mapHeight) + "\n";

  mapContent += "MAPSCAL " + std::to_string(map->mapScaleX) + "x" +
                std::to_string(map->mapScaleY) + "\n";

  mapContent += "MAP\n";
  // Map data
  for (auto tile : map->data.mapTiles) {
    mapContent += "TILE " + tile + "\n";
  }
  mapContent += "ENDMAP\n";

  SDL_Log("Saving map to: %s", filepath.c_str());

  std::ofstream mapFile;
  mapFile.open(filepath, std::ios::trunc);

  mapFile << mapContent;
  mapFile.close();
}
