// file: $isip/class/dstr/ColorHash/ColorHash.h
// version: $Id: ColorHash.h 10640 2007-01-27 02:36:04Z tm334 $
//

// make sure definitions are only made once:
//
#ifndef ISIP_COLOR_HASH
#define ISIP_COLOR_HASH

// forward class definitions
//
template<class TVertex> class GVKey;

// isip include files
//
#ifndef ISIP_HASH_TABLE
#include <HashTable.h>
#endif

#ifndef ISIP_NAME_MAP
#include <NameMap.h>
#endif

#ifndef ISIP_GRAPH_VERTEX
#include <GraphVertex.h>
#endif

// ColorHash: the main function of this class is to create a one-to-one mapping
// between a graph vertex pointer and the corresponding color of the vertex.
// we use a separate class for this so that it is possible to have a
// graph vertex without the notion of color, which would waste memory
// for applications not needing color.
//
template<class TObject>
class ColorHash : public DstrBase {
  
  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:

  // define the class name. also include names for the inner classes.
  //
  static const String CLASS_NAME;
  static const String GV_KEY_CLASS_NAME;
  static const String GV_COLOR_CLASS_NAME;

  //---------------------------------------------------------------------------
  //
  // inner classes
  //
  //---------------------------------------------------------------------------

  // GVColor: the main function of this class is to act a wrapper for the
  // graph vertex class. this class stores the color values of the graph
  // vertices that tell us if the vertex has been previously visited.
  //
  class GVColor {
  
    //-------------------------------------------------------------------------
    //
    // protected data
    //
    //-------------------------------------------------------------------------
   protected:
    
    // GVColor value
    //
    Integral::COLOR color_d;
    
    //-------------------------------------------------------------------------
    //
    // public methods
    //
    //-------------------------------------------------------------------------
   public:
    
    // method: name
    //
    static const String& name() {
      return ColorHash<Char>::GV_COLOR_CLASS_NAME;
    }
    
    // method: debug
    //
    boolean debug(const unichar* message_a) const {
      
      // build a debug string
      //
      String output;
      output.debugStr(name(), message_a, L"color",
		      NameMap::COLOR_MAP((long)color_d));
      Console::put(output);
      
      // exit gracefully
      //
      return true;
    }

    // method: destructor
    //
    ~GVColor() {}
    
    // method: default constructor
    //
    GVColor(Integral::COLOR arg = Integral::DEF_COLOR) {
      color_d = arg;
    }
    
    // method: copy constructor
    //
    GVColor(GVColor& arg) {
      assign(arg);
    }

    // method: assign
    //
    boolean assign(const GVColor& arg) {
      color_d = arg.color_d;
      return true;
    }
    
    // method: eq
    //
    boolean eq(const GVColor& arg) const {
      return (color_d == arg.color_d);
    }
    
    // method: clear
    //
    boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE) {
      return (color_d = Integral::DEF_COLOR);
    }
    
    // method: assign
    //
    boolean assign(const Integral::COLOR arg) {
      color_d = arg;
      return true;
    }
    
    // method: get
    //
    Integral::COLOR get() {
      return color_d;
    }
  };

  //----------------------------------------
  //
  // other important constants
  //
  //----------------------------------------
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  // default values
  //
  
  // default arguments to methods
  //

  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------

  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // define a typedef for the ColorHash template
  //
  typedef ColorHash<TObject> CHASH;

  // define the internal hash table instance
  //
  HashTable<GVKey<TObject>, GVColor> hash_d;
  
  // debugging parameters
  //
  static Integral::DEBUG debug_level_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:





  // static methods:
  //
  static const String& name();
  
  // method: setDebug
  //
  static boolean setDebug(Integral::DEBUG arg) {
    debug_level_d = arg;
    return true;
  }

  // other debug methods
  //
  boolean debug(const unichar* message) const;

  // method: destructor
  //
  ~ColorHash() {}
  
  // method: default constructor
  //
  ColorHash() {}
  
  // method: copy constructor
  //
  ColorHash(const CHASH& arg) {
    assign(arg);
  }

  // method: assign
  //
  boolean assign(const CHASH& arg) {
    return hash_d.assign(arg.hash_d);
  }
  
  // method: operator=
  //
  CHASH operator=(const CHASH& arg) {
    assign(arg);
    return *this;
  }

  // method: eq
  //
  boolean eq(const CHASH& arg) const {
    return hash_d.eq(arg.hash_d);
  }
  
  // i/o methods:
  //  these methods are not defined for this class
  //
  
  // memory-management methods:
  //  these methods are not defined for this class
  //

  // method: clear
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE) {
    return hash_d.clear(cmode);
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  hash table property methods
  //
  //---------------------------------------------------------------------------
  
  // method: getNumItems
  //
  long getNumItems() const {
    return hash_d.getNumItems();
  }

  // method: isEmpty
  //
  boolean isEmpty() const {
    return hash_d.isEmpty();
  }
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  hash table get and set methods
  //
  //---------------------------------------------------------------------------
  
  // method: get
  //
  Integral::COLOR get(const GraphVertex<TObject>* key) {
    const GVKey<TObject> arg1(key);
    GVColor* col = hash_d.get(arg1);
    if (col == (GVColor*)NULL) {
      Error::handle(name(), L"get", ERR, __FILE__, __LINE__);
      return (Integral::COLOR)NULL;
    }
    return col->get();
  }

  // method: get
  //
  const Integral::COLOR get(const GraphVertex<TObject>* key) const {
    const GVKey<TObject> arg1(key);
    GVColor* col = hash_d.get(arg1);
    if (col == (GVColor*)NULL) {
      Error::handle(name(), L"get", ERR, __FILE__, __LINE__);
      return (Integral::COLOR)NULL;
    }
    return col->get();
  }

  // method: set
  //
  boolean set(const GraphVertex<TObject>* key, Integral::COLOR value) {
    const GVKey<TObject> arg1(key);
    GVColor* col = hash_d.get(arg1);
    if (col == (GVColor*)NULL) {
      Error::handle(name(), L"set", ERR, __FILE__, __LINE__);
      return (Integral::COLOR)NULL;
    }
    return col->assign(value);
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  hash table insert and remove methods
  //
  //---------------------------------------------------------------------------
  
  // method: insert
  //
  boolean insert(const GraphVertex<TObject>* key, Integral::COLOR value) {
    const GVKey<TObject> arg1(key);
    GVColor arg2(value);
    return hash_d.insert(arg1, &arg2);
  }

  // method: remove
  //
  boolean remove(const GraphVertex<TObject>* key) {
    GVKey<TObject> arg1(key);
    if (!hash_d.remove(arg1)) {
      return Error::handle(name(), L"remove", ERR, __FILE__, __LINE__);
    }
    return true;
  }

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  hash table contains methods
  //
  //---------------------------------------------------------------------------
  
  // method: containsKey
  //
  boolean containsKey(const GraphVertex<TObject>* key) const {
    const GVKey<TObject> arg1(key);
    return hash_d.containsKey(arg1);
  }

  // method: containsValue
  //
  boolean containsValue(const Integral::COLOR value) const {
    GVColor arg1(value);
    return hash_d.containsValue(&arg1);
  }
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

};

// GVKey: the main function of this class is to make pointers to the graph
// vertex class hashable. this class contains a pointer to a graph vertex
// and determines the hash index that corresponds to the hash index.
//
template<class TVertex>
class GVKey : public Node<GraphVertex<TVertex > > {
  
  //-------------------------------------------------------------------------
  //
  // public methods
  //
  //-------------------------------------------------------------------------
public:
  
  // method: name
  //
  static const String& name() {
    
    // create the static name string for this class and return it
    //
    static String cname(ColorHash<TVertex>::GV_KEY_CLASS_NAME);
    cname.clear();
    cname.concat(ColorHash<TVertex>::CLASS_NAME);
    cname.concat(L"<");
    cname.concat(TVertex::name());
    cname.concat(L">");
    
    // return the name
    //
    return cname;
  }
  
  // method: debug
  //
  boolean debug(const unichar* message_a) const {
    
    // build a debug string
    //
    String output;
    String value;
    value.assign(this->item_d);
    output.debugStr(name(), message_a, L"item", value);
    Console::put(output);
    
    // exit gracefully
    // 
    return true;
  }
  
  // method: destructor
  //
  ~GVKey() {}
  
  // method: default constructor
  //
  GVKey() {}
  
  // method: copy constructor
  //
  GVKey(GVKey<TVertex>& arg) {
    this->item_d = arg.item_d;
  }
  
  // method: copy constructor
  //
  GVKey(const GraphVertex<TVertex>* arg) {
    this->item_d = const_cast<GraphVertex<TVertex>*>(arg);
  }
  
  // method: assign
  //
  boolean assign(const GVKey<TVertex>& arg) {
    this->item_d = arg.item_d;
    return true;
  }
  
  // method: eq
  //
  boolean eq(const GVKey<TVertex>& arg) const {
    return (this->item_d == arg.item_d);
  }
};

//-----------------------------------------------------------------------------
//
// we define non-integral constants at the end of class definition for
// templates (for non-templates these are defined in the default constructor)
//      
//-----------------------------------------------------------------------------

// constants: required constants such as the class name
//
template <class TObject>
const String ColorHash<TObject>::CLASS_NAME(L"ColorHash");

template <class TObject>
const String ColorHash<TObject>::GV_KEY_CLASS_NAME(L"GVKey");

template <class TObject>
const String ColorHash<TObject>::GV_COLOR_CLASS_NAME(L"GVColor");

// static instantiations: debug level
//
template <class TObject>
Integral::DEBUG ColorHash<TObject>::debug_level_d = Integral::NONE;

// below are all the methods for the ColorHash template class
//

//-----------------------------------------------------------------------------
//
// required static methods
//
//-----------------------------------------------------------------------------

// method: name
//
// arguments: none
//
// return: a static String& containing the class name
//
// this method returns the class name
//
template <class TObject>
const String& ColorHash<TObject>::name() {

  // create the static name string for this class and return it
  //
  static String cname(CLASS_NAME);
  cname.clear();
  cname.concat(CLASS_NAME);
  cname.concat(L"<");
  cname.concat(TObject::name());
  cname.concat(L">");

  // return the name
  //
  return cname;
}

// method: debug
//
// arguments:
//  const unichar* message: (input) information message
//
// return: a boolean value indicating status
//
// this method dumps the contents of an object to the console
// 
template<class TObject>
boolean ColorHash<TObject>::debug(const unichar* message_a) const {

  // build a debug string
  //
  String val;
  String output;
  output.debugStr(name(), message_a, L"hash_d");
  Console::put(output);
  
  Console::increaseIndention();

  // dump the this pointer
  //
  hash_d.debug(L"");
  
  // that's it for sub-items, decrease indentation
  //
  Console::decreaseIndention();

  // exit gracefully
  // 
  return true;
}

// end of include file
// 
#endif
