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

#include "MaterialManagement.h"
#include "../Util/Funcs.h"
#include "../Base/LogManagement.h"
#include "../Util/TextureManagement.h"

BEGIN_TEG_NAMESPACE();

MaterialManagement::MaterialManagement() {}

MaterialManagement::~MaterialManagement() { 
  // 
  release();
}

// Method to load a material file.
void MaterialManagement::load(const std::tstring& path) {
  // Try to open the file.
  FILE* f = fopen(path.c_str(), "r"); 
  if (f == NULL) {
    PRINT_LOG(TYPE_ERROR, "Error: Cannot open material file: \'%s\'", path.c_str());
    return;
  }

  SmartPointer<Material> mat = new Material();

  // Load the materials in the file.
  const int MAX_LONG = 1000; _TCHAR buffer[MAX_LONG];
  while (fgets(buffer, MAX_LONG, f) != NULL) {
    // Get the line type.
    _TCHAR lineType[MAX_LONG];
    sscanf(buffer, "%s", lineType);

    // Check if is a comment line.
    if (lineType[0] == '#') continue; // Process the next line.

    if (strcmp(lineType, _T("newmtl")) == 0) {
      // If is not the first material.
      if(mat->name != _T("")) add(mat);

      // Create a new material and set the mateial name.
      mat = new Material();
      _TCHAR materialName[MAX_LONG];
      sscanf(buffer, "%*s %s", materialName);
      mat->name = materialName;
    } else if (strcmp(lineType, _T("Ka")) == 0) {
      // Get ambient component.
      sscanf(buffer, "%*s %f %f %f", &mat->ambient.x, &mat->ambient.y, &mat->ambient.z);
    } else if (strcmp(lineType, _T("Kd")) == 0) {
      // Get diffuse component.
      sscanf(buffer, "%*s %f %f %f", &mat->diffuse.x, &mat->diffuse.y, &mat->diffuse.z);
    } else if (strcmp(lineType, _T("Ks")) == 0) {
      // Get specular component.
      sscanf(buffer, "%*s %f %f %f", &mat->specular.x, &mat->specular.y, &mat->specular.z);
    } else if (strcmp(lineType, _T("Ns")) == 0) {
      // Get shininesss component.
      sscanf(buffer, "%*s %f", &mat->shininess);
    } else if (strcmp(lineType, _T("d")) == 0 || strcmp(lineType, _T("Tr")) == 0) {
      // Get alpha component.
      sscanf(buffer, "%*s %f", &mat->alpha); mat->setAlpha(mat->alpha);
    } else if (strcmp(lineType, _T("illum")) == 0) {
      // Get illum type.
      sscanf(buffer, "%*s %d", &mat->illum);
    } else if (strcmp(lineType, _T("map_Ka")) == 0 || strcmp(lineType, _T("map_Kd")) == 0) {
      // Get texture file path.
      _TCHAR texturePath[MAX_LONG];
      sscanf(buffer, "%*s %s", texturePath);
      mat->fileName = texturePath;
      mat->textureId = LOAD_TEXTURE(GetAPathFromOne(path, texturePath).c_str());
	} else if (strcmp(lineType, _T("wrap_option")) == 0) {
      int wrap_option; sscanf(buffer, "%*s %d", &wrap_option);
	  mat->wrap_option = wrap_option;
    }
  }
  // Store the last material.
  if (mat->name != _T("")) add(mat);

  fclose(f);
}

// Method to store a material.
void MaterialManagement::add(const SmartPointer<Material>& material) {
  if (materials.find(material->name) == materials.end())
    materials.insert(std::pair<std::tstring, SmartPointer<Material>> (material->name, material));
}

// Method to get a material.
SmartPointer<Material> MaterialManagement::get(const std::tstring& materialName) {
  if (materials.find(materialName) == materials.end())
    return materials[_T("SceneNavigator_Default__")];
  return materials[materialName];
}

// Method initialize the materials in the app.
void MaterialManagement::init() {
  // Add a default material.
  materials.insert(std::pair<std::tstring, SmartPointer<Material> > (
      _T("SceneNavigator_Default__"), new Material()));
}

// Method to free all the Materials in the app.
void MaterialManagement::release(void) {
  materials.clear();
}

END_TEG_NAMESPACE();
