// Author: Juan Carlos De Abreu (jcabreur@gmail.com)

#include "ShadowInstance.h"

BEGIN_TEG_NAMESPACE();

// Constructor
ShadowInstance::ShadowInstance()
    : shadow2DL(0), shadow3DL(0), calculateShadow(true) {
  // Initialize the attributes
}

//ShadowInstance::ShadowInstance(const ModelObj& model)
ShadowInstance::ShadowInstance(const SmartPointer<IModel>& model)
    : shadow2DL(0), shadow3DL(0), calculateShadow(true) {
  init(model);
}

// Destructor
ShadowInstance::~ShadowInstance() {
  glDeleteLists(shadow2DL, 1);
  glDeleteLists(shadow3DL, 1);
}

// Method
void ShadowInstance::init(const SmartPointer<IModel>& model) {
  const int nGroups = model->groupList.size();
  for (int i = 0; i < nGroups; ++i) {
    const int nFaces = model->groupList[i].faceList.size();
    faceList.push_back(std::vector<ShadowPlane> (nFaces));
  }
}

// Operator
void ShadowPlane::operator = (const ShadowPlane& s) {
  plane = s.plane; neigh = s.neigh; visible = s.visible;
}

// Method to load a shadowInstance.
bool ShadowInstance::load(const std::tstring& path) {
  // Try to open the file for read.
  FILE* f = fopen(path.c_str(), "rb");
  if (f == NULL) {
    PRINT_LOG(TYPE_WARNING, "Can't opent the file %s for read!", path.c_str());
    return false;
  }

	// Load the head of the file.
  _TCHAR buffer[100]; memset(buffer, 0, sizeof(buffer));
  int nBytesRead = fread(buffer, sizeof(_TCHAR), 12, f);
  if (strcmp(buffer, _T("VOLUMESHADOW")) != 0) return false;

  // Load the number of groups and the data of each group.
  int nGroups, nPlanes;
  nBytesRead = fread(&nGroups, sizeof(int), 1, f); faceList.resize(nGroups);
  for (int i = 0; i < nGroups; ++i) {
    nBytesRead = fread(&nPlanes, sizeof(int), 1, f); faceList[i].resize(nPlanes);
    for (int j = 0; j < nPlanes; ++j) {
      faceList[i][j].load(f);
    }
  }
  fclose(f);
  return true;
}

// Method to save a ShadowInstance.
bool ShadowInstance::save(const std::tstring& path) const {
  // Try to open the file for write.
  FILE* f = fopen(path.c_str(), "wb");
  if (f == NULL) {
    PRINT_LOG(TYPE_WARNING, "Can't open or create the file %s for write!", path.c_str());
    return false;
  }

  // Save the head of the file.
  fwrite(_T("VOLUMESHADOW"), sizeof(_TCHAR), 12, f);

  // Save the number of groups and the data of each group.
  const int nGroups = static_cast<int> (faceList.size());
  fwrite(&nGroups, sizeof(int), 1, f);
  for (int i = 0; i < nGroups; ++i) {
    const int nPlanes = static_cast<int> (faceList[i].size());
    fwrite(&nPlanes, sizeof(int), 1, f);
    for (int j = 0; j < nPlanes; ++j) {
      faceList[i][j].save(f);
    }
  }
  fclose(f);
  return true;
}

// Method to load a data plane.
bool ShadowPlane::load(FILE* f) {
  int nByestRead;
  nByestRead = fread(plane.values, sizeof(float), 4, f);
  nByestRead = fread(neigh.values, sizeof(unsigned int), 3, f);
  return true;
}

// Method to save a data plane.
bool ShadowPlane::save(FILE* f) const {
  fwrite(plane.values, sizeof(float), 4, f);
  fwrite(neigh.values, sizeof(unsigned int), 3, f);
  return true;
}

END_TEG_NAMESPACE();
