/**
 * Copyright (c) 2022 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#include "../../utils/common.hpp"
#include "../../utils/file.hpp"
#include "../../utils/image.hpp"

int main(int argc, char *argv[]) {
  char *in;
  char *out;
  FILE *file;
  char path[FILENAME_MAX + 1];
  int w, h, channels, cols, rows;
  stbi_uc *dataImageRaw;
  int gapX, gapY, borderX, borderY;

  if(argc < 5) {
    printf("Invalid number of arguments");
    return 1;
  }

  in = argv[1];
  out = argv[2];
  gapX = 0, gapY = 0, borderX = 0, borderY = 0;

  cols = atoi(argv[3]);
  if(cols <= 0) {
    printf("Columns is invalid\n");
    return 1;
  }

  rows = atoi(argv[4]);
  if(rows <= 0) {
    printf("Rows is invalid");
    return 1;
  }

  if(argc >= 6) {
    gapX = atoi(argv[5]);
    if(gapX <= 0) {
      printf("Gap X is invalid\n");
      return 1;
    }
  }

  if(argc >= 7) {
    gapY = atoi(argv[6]);
    if(gapY <= 0) {
      printf("Gap Y is invalid\n");
      return 1;
    }
  }

  if(argc >= 8) {
    borderX = atoi(argv[7]);
    if(borderX <= 0) {
      printf("Border X is invalid\n");
      return 1;
    }
  }

  if(argc >= 9) {
    borderY = atoi(argv[8]);
    if(borderY <= 0) {
      printf("Border Y is invalid\n");
      return 1;
    }
  }

  // Normalize slashes
  fileNormalizeSlashes(in);
  fileNormalizeSlashes(out);

  // Check the output doesn't already exist
  sprintf(path, "%s.tileset", out);
  file = fopen(path, "rb");
  if(file != NULL) {
    fclose(file);
    return 0;
  }

  // Read in the original texture
  file = fopen(in, "rb");
  if(file == NULL) {
    printf("Failed to open file!\n");
    return 1;
  }
  
  // Read image data
  dataImageRaw = stbi_load_from_file(file, &w, &h, &channels, STBI_rgb_alpha);
  if(dataImageRaw == NULL) {
    printf("Failed to load input texture!\n");
    return 1;
  }
  fclose(file);
  free(dataImageRaw);

  if(w <= 0 || h <= 0) {
    printf("Reading image failed (corrupted?)\n");
    return 1;
  }

  // Calculate division sizes (pixels)
  int divX = (w - (borderX * 2) - (gapX * (cols - 1))) / cols;
  int divY = (h - (borderY * 2) - (gapY * (rows - 1))) / rows;

  // Calculate the division sizes (units)
  float tdivX = (float)divX / (float)w;
  float tdivY = (float)divY / (float)h;

  // Output buffer prep
  char *buffer = (char *)malloc(sizeof(char) * (cols * rows * 48 + 48 + 48));
  buffer[0] = '\0';

  sprintf(buffer, "%i|%i|%i|%i|", cols, rows, divX, divY);

  // Now prep tileset.
  for(float y = 0; y < rows; y++) {
    for(float x = 0; x < cols; x++) {
      float ux0 = ((float)borderX + ((float)divX * x) + ((float)gapX * x)) / (float)w;
      float ux1 = ux0 + tdivX;
      float uy0 = ((float)borderY + ((float)divY * y) + ((float)gapY * y)) / (float)h;
      float uy1 = uy0 + tdivY;
      sprintf(buffer, "%s%f,%f,%f,%f|", buffer, ux0, ux1, uy0, uy1);
    }
  }

  // Open output file
  fileMkdirp(path);
  file = fopen(path, "wb");
  if(file == NULL) {
    free(buffer);
    printf("Invalid tileset file out!\n");
    return 1;
  }

  // Write and close
  fwrite(buffer, sizeof(char), strlen(buffer), file);
  fclose(file);
  free(buffer);

  return 0;
}