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

#include "assert/assertgl.hpp"
#include "assert/assert.hpp"
#include "ShaderStage.hpp"

using namespace Dawn;

ShaderStage::ShaderStage(
  const enum ShaderStageType type,
  const std::string source
) : IShaderStage(type) {
  // Get OpenGL Shader Type
  GLenum shaderType;
  switch(this->type) {
    case ShaderStageType::VERTEX:
      shaderType = GL_VERTEX_SHADER;
      break;

    case ShaderStageType::FRAGMENT:
      shaderType = GL_FRAGMENT_SHADER;
      break;

    // case ShaderStageType::COMPUTE:
    //   shaderType = GL_COMPUTE;
    //   break;

    default:
      assertUnreachable("Unknown ShaderStageType");
  }

  // Initialize the shader
  this->id = glCreateShader(shaderType);
  assertNoGLError();

  // Compile the shader
  auto cSource = source.c_str();
  glShaderSource(this->id, 1, &cSource, NULL);
  assertNoGLError();
  glCompileShader(this->id);
  assertNoGLError();
  
  // glShaderBinary(1, &this->id, GL_SHADER_BINARY_FORMAT_SPIR_V, source.data(), source.size());
  // assertNoGLError();
  // glSpecializeShader(this->id, "main", 0, NULL, NULL);
  // assertNoGLError();

  // Validate
  GLint status;
  glGetShaderiv(this->id, GL_COMPILE_STATUS, &status);
  assertNoGLError();

  if(!status) {
    // Failed to compile
    GLint logLength;
    glGetShaderiv(this->id, GL_INFO_LOG_LENGTH, &logLength);
    assertNoGLError();

    GLchar *log = new GLchar[logLength];
    glGetShaderInfoLog(this->id, logLength, NULL, log);
    assertNoGLError();
    assertUnreachable("Failed to compile shader stage %i:\n%s", type, log);
  }
}

ShaderStage::~ShaderStage() {
  if(this->id != -1) {
    glDeleteShader(this->id);
    assertNoGLError();
  }
}