// __author__ = Juan Carlos De Abreu (jcabreur@gmail.com)

#include "Material.h"
#include "../Base/LogManagement.h"
#include "../Model/Group.h"
#include "../util/TextureManagement.h"

BEGIN_TEG_NAMESPACE();

// Material constructor.
Material::Material() {
  // Initialize the material attributes.
  name = "";
  fileName = "";
  alpha = 1.0f;
  shininess = 8.0f;
  illum = SPECULAR_HIGHLIGHTS;
  ambient.set(0.1f, 0.1f, 0.1f);
  diffuse.set(0.8f, 0.8f, 0.8f);
  specular.set(0.7f, 0.7f, 0.7f);
  emission.set(0.0f, 0.0f, 0.0f);
  textureId = 1; // Use the default texture.
  wrap_option = 0;
}

// Material destructor.
Material::~Material() { }

// Method set the material property as actual.
void Material::apply() const {
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient.values);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse.values);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular.values);
  glMaterialfv(GL_FRONT, GL_EMISSION, emission.values);
  glMaterialf(GL_FRONT, GL_SHININESS, illum == 1 ? 0.0f : shininess);
}

// begin and end methods delimit the material properties.
void Material::begin(const int& renderMode) const {
  // If has a texture then apply.
  if (renderMode & Group::TEXTURE && fileName != "") {
    glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, textureId);
	TextureManagement::GetInstance().set_option(wrap_option);
  }
  if (renderMode & Group::MATERIAL) apply();
}

void Material::end(const int& renderMode) const {
  // Disable the texture
  if(renderMode & Group::TEXTURE && fileName != "") {
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);
  }
}

// Method to update the alpha component
void Material::setAlpha(const float& alpha_) {
  alpha = ambient.w = diffuse.w = specular.w = emission.w = alpha_;
}

// Method to make a copy of this material.
SmartPointer<Material> Material::copy(void) const {
  // Create a new material and copy all the data.
  SmartPointer<Material> mat = new Material();
  mat->name = name;
  mat->fileName = fileName;
  mat->alpha = alpha;
  mat->shininess = shininess;
  mat->illum = illum;
  mat->ambient = ambient;
  mat->diffuse = diffuse;
  mat->specular = specular;
  mat->emission = emission;
  mat->textureId = textureId;
  return mat;
}

END_TEG_NAMESPACE();
