#include "shaders.h"
#include "file.h"


bool load_shaders(Shader *shader, string vertex_shader_filepath, string fragment_shader_filepath) {
  u32 vertex_shader = load_shader(vertex_shader_filepath, GL_VERTEX_SHADER);
  if (!vertex_shader) {
    return false;
  }

  u32 fragment_shader = load_shader(fragment_shader_filepath, GL_FRAGMENT_SHADER);
  if (!fragment_shader) {
    return false;
  }

  shader->program = glCreateProgram();
  glAttachShader(shader->program, vertex_shader);
  glAttachShader(shader->program, fragment_shader);
  glLinkProgram(shader->program);

  s32 is_program_linked;
  glGetProgramiv(shader->program, GL_LINK_STATUS, &is_program_linked);
  if (!is_program_linked) {
    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
    return false;
  }

  s32 ubo_index = glGetUniformBlockIndex(shader->program, "Matrices");
  glUniformBlockBinding(shader->program, ubo_index, 0);

  glDeleteShader(vertex_shader);
  glDeleteShader(fragment_shader);

  return true;
}

void cleanup_shader(Shader *shader) {
  glDeleteProgram(shader->program);
}

u32 load_shader(string filepath, u32 shader_type) {
  string shader_as_text; 
  shader_as_text = load_file_to_string(filepath);

  const char*shader_source = shader_as_text.c_str();
  u32 shader = glCreateShader(shader_type);
  glShaderSource(shader, 1, (const GLchar**) &shader_source, 0);
  glCompileShader(shader);

  s32 is_shader_compiled;
  glGetShaderiv(shader, GL_COMPILE_STATUS, &is_shader_compiled);
  if (!is_shader_compiled) {
    return 0;
  }

  return shader;
}

void use_shader(Shader *shader) {
  glUseProgram(shader->program);
}
