/**
* @file ClassNames.h
* @brief simple interface for class name confusion
* @author Erik Rodner, Alexander Freytag
* @date 02/08/2008, latest update 29-01-2014 (dd-mm-yyyy)

*/
#ifndef CLASSNAMESINCLUDE
#define CLASSNAMESINCLUDE

#include "core/image/ImageT.h"
#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"

#include <string>
#include <map>

// in future we should replace this with 
// unordered_map, but it is still experimental but standard c++
#ifdef WIN32
#ifdef NICE_USELIB_BOOST
#include <boost/unordered_map.hpp>
#endif
#else
//#include <ext/hash_map>
#ifdef __clang__
#include <unordered_map>
#else
#include <tr1/unordered_map>
#endif
#endif

#include "core/basics/Config.h"
#include "core/basics/Persistent.h"


namespace OBJREC {

/** simple interface for class name confusion */
class ClassNames : public NICE::Persistent
{

  protected:

    std::map<std::string, std::string> tbl_code_text;
    std::map<std::string, std::string> tbl_text_code;
    std::map<int, std::string> tbl_classno_code;
    std::map<std::string, int> tbl_code_classno;
#if defined WIN32 && defined NICE_USELIB_BOOST
    boost::unordered_map<long, int> tbl_color_classno;
#else
//	__gnu_cxx::hash_map<long, int> tbl_color_classno;
#ifdef __clang__
    std::unordered_map<long, int> tbl_color_classno;
#else
    std::tr1::unordered_map<long, int> tbl_color_classno;
#endif
#endif
    std::map<int, long> tbl_classno_color;


    int maxClassNo;

  public:

    /** simple constructor */
    ClassNames();

    /** copy constructor */
    ClassNames ( const ClassNames & cn );

    /** create sub selection */
    ClassNames ( const ClassNames & cn,
                 const std::string & classselection );

    /** simple destructor */
    virtual ~ClassNames();

    /** get the readable class number of a class number */
    std::string text ( int classno ) const;

    /** get the class code (e.g. ascii code) of a class number */
    std::string code ( int classno ) const;

    /** get the class number corresponding to the code */
    int classno ( std::string code ) const;

    /** get the class number corresponding to the name */
    int classnoFromText ( std::string text ) const;

    /** number of classes */
    int numClasses () const;
    void getSelection ( const std::string & classselection,
                        std::set<int> & classnos ) const;

    /** add new class information
     * @param classno class number
     * @param code class code (such as ascii number or just the name)
     * @param text class name as readable ascii representation
     */
    void addClass ( int classno, const std::string & code,
                    const std::string & text );

    bool readFromConfig ( const NICE::Config & datasetconf,
                          const std::string & classselection );

    /** is there any class with this class number */
    bool existsClassno ( int classno ) const;
    /** is there any class with this class code */
    bool existsClassCode ( const std::string & classcode ) const;

    int getMaxClassno () const;

    void getRGBColor ( int classno, int & r, int & g, int & b ) const;

    void getClassnoFromColor ( int & classno, int r, int g, int b ) const;

    /** colorize a labeled image using color information given in the class
     *  information file */
    void labelToRGB ( const NICE::Image & img, NICE::ColorImage & rgb ) const;

    int getBackgroundClass () const;

    /** restore classnames in the format <classtext> <classcode> <classno> */
    void restore ( std::istream & is, int format = 0 );

    /** store classnames in the format <classtext> <classcode> <classno> */
    void store ( std::ostream & os, int format = 0 ) const;

    /** clear class information */
    void clear ();
};


} // namespace

#endif
