#ifndef _FACE_H
#define _FACE_H

#include <limits.h>
#include "boundingbox.h"
#include "edge.h"
#include "vertex.h"

// ===========================================================

class Face {

public:

  // ========================
  // CONSTRUCTOR & DESTRUCTOR
  Face(const Vec3f &c, const Vec3f &e) {
    edge = NULL;
    color = c; 
    emit = e; 
  }
  ~Face() {}

  // here's the hash function to use for faces so they
  // can be efficiently accessed within the Bag data structure
  static void extract_func(Face *t, int &a, int &b, int &c, int &d) {
    a = (*t)[0]->getIndex(); 
    b = (*t)[1]->getIndex(); 
    c = (*t)[2]->getIndex();
    d = (*t)[3]->getIndex();
  }

  // =========
  // ACCESSORS
  Vertex* operator[](int i) const { 
    assert (edge != NULL);
    if (i==0) return edge->getVertex();
    if (i==1) return edge->getNext()->getVertex();
    if (i==2) return edge->getNext()->getNext()->getVertex();
    if (i==3) return edge->getNext()->getNext()->getNext()->getVertex();
    assert(0);
  }
  Edge* getEdge() const { 
    assert (edge != NULL);
    return edge; 
  }

  // =========
  // MODIFIERS
  void setEdge(Edge *e) {
    assert (edge == NULL);
    edge = e;
  }

  // ===================
  // RADIOSITY ACCESSORS
  Vec3f getColor() const { return color; }
  Vec3f getEmit() const { return emit; }
  float getArea() const;
  int getRadiosityPatchIndex() const { return radiosity_patch_index; }

  // ===================
  // RADIOSITY MODIFIERS
  void setRadiosityPatchIndex(int i) { radiosity_patch_index = i; }

  // NOTE: If you want to modify a face, remove it from the mesh,
  // delete it, create a new copy with the changes, and re-add it.
  // This will ensure the edges get updated appropriately.

protected:

  // don't use this constructor
  Face& operator = (const Face &f) { assert(0); }
  
  // ==============
  // REPRESENTATION
  Edge *edge;
  
  // radiosity variables
  Vec3f emit;   // the energy emitted per unit of patch area
  Vec3f color;  // the color (diffuse reflectivity, BRDF)
  int radiosity_patch_index;  // an awkward pointer to this patch in the Radiosity patch array

};

// ===========================================================

#endif

