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

#include "texture.h"

// Due to some compiler bullshit, this is here.
#ifndef  STB_IMAGE_IMPLEMENTATION
  #define STB_IMAGE_IMPLEMENTATION
  #include <stb_image.h>
#endif

void textureInit(texture_t *texture, int32_t width, int32_t height,
  pixel_t *pixels
) {
  texture->width = width;
  texture->height = height;

  // Generate a texture ID and bind.
  glGenTextures(1, &texture->id);
  glActiveTexture(GL_TEXTURE0);
  glBindTexture(GL_TEXTURE_2D, texture->id);

  // Setup our preferred texture params
  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  // Start by buffering all transparent black pixels.
  if(pixels == NULL) {
    // TODO: I can optimize this, I think the GPU can default this somehow
    pixels = calloc(width * height, sizeof(pixel_t));
    glTexImage2D(
      GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
      GL_RGBA, GL_UNSIGNED_BYTE, pixels
    );
    free(pixels);
  } else {
    glTexImage2D(
      GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
      GL_RGBA, GL_UNSIGNED_BYTE, pixels
    );
  }
  
  glBindTexture(GL_TEXTURE_2D, 0);
}

void textureBufferPixels(texture_t *texture,
  int32_t x, int32_t y, int32_t width, int32_t height, pixel_t *pixels
) {
  glBindTexture(GL_TEXTURE_2D, texture->id);
  glTexSubImage2D(GL_TEXTURE_2D, 0,
    x, y, width, height,
    GL_RGBA, GL_UNSIGNED_BYTE, pixels
  );
}

void textureDispose(texture_t *texture) {
  glDeleteTextures(1, &texture->id);
}