/// Dictionary.cpp
/**
*/

/*
  Main workhorse for getting field definitions for various formats.
*/

#include "Dictionary.h"

using namespace jcs;

///
/** Dictionary class, used to maintain tuples of DICOM field definitions.
    Parent class of more-specific Dictionaries.
    Field definitions are maintained as a TagMap and a StringMap.
*/
Dictionary::Dictionary(const std::string& dname) : mDictionaryName(dname)
{
  NULL_ENTRY = DicomElement(DicomTag(0x0000, 0x0000), "");
  if (mDictionaryName.compare (fnDicom) == 0) {
#include "DicomDictionary.h"
  } else if (mDictionaryName.compare (fnExcite) == 0) {
#include "ExciteDictionary.h"
  } else if (mDictionaryName.compare (fnNumaris) == 0) {
#include "NumarisDictionary.h"
  } else if (mDictionaryName.compare (fnPhilips) == 0) {
#include "PhilipsDictionary.h"
  } else {
    wxLogError (_T("Error initializing dictionary."));
  }
}


///
/** Look up a DICOM element in mTagMap.
    \param tag A reference to a DicomTag.
    \return A DicomElement object.
*/
const DicomElement
Dictionary::Lookup(const DicomTag& tag) const
{
  if (mTagMap.size() == 0) {
    wxLogError(_T("Error: dictionary tag map %s is of zero size."),
    wxString(mDictionaryName.c_str(), wxConvLocal).c_str());
    return DicomElement(tag, "unknown");
  }
  if (mTagMap.count(tag) == 0) {
    return DicomElement(tag, "unknown");
  }
  else {
    DicomElement e = (*mTagMap.find(tag)).second;
    return e;
  }
}


///
/** Look up a DICOM element in mStringMap.
    \param desc Key to seek.
    \return A DicomElement object.
*/
const DicomElement
Dictionary::Lookup(const std::string& desc) const
{
  if (mStringMap.size() == 0) {
    wxLogError(_T("Error: dictionary string map %s is of zero size."), wxString(mDictionaryName.c_str(), wxConvLocal).c_str());
    return NULL_ENTRY;
  }
  if (mStringMap.count(desc) == 0) {
    wxLogError(_T("%s not in dictionary"), wxString(desc.c_str(), wxConvLocal).c_str());
    return NULL_ENTRY;
  }
  else {
    DicomElement e = (*mStringMap.find(desc)).second;
    return e;
  }
}


///
/**
*/
static std::string
GetDescription(std::pair<DicomTag, DicomElement> tag_pair)
{
  return tag_pair.second.description;
}


///
/** Look up tag identified by string 's' in dictionary 'dict'.
    \param s A string to seek.
    \param dict The dictionary in which to seek.
    \return A DicomTag object.
*/
DicomTag
jcs::Tag(const std::string& s, 
const Dictionary* dict)
{
  return dict->Lookup(s).tag;
}


///
/**
*/
std::vector<std::string>
Dictionary::TagList() const
{
  std::vector<std::string> v;
  v.reserve(mTagMap.size());
  std::transform(mTagMap.begin(), mTagMap.end(), std::back_inserter(v), GetDescription);
  return v;
}


///
/** Add the given DicomElement to mTagMap and mStringMap.
    \param e A reference to the DicomElement to be added.
*/
void
Dictionary::mAddEntry(const DicomElement& e)
{
  mTagMap[e.tag] = e;
  mStringMap[e.description] = e;
}
