#include "namespaces.h"
#include <cassert>

namespace aka2 {

const id_type namespace_map::register_namespace_uri(const std::string &uri){
  id_type id = get_namespace_id(uri);
  if (id != unregistered_token)
    return id;

  std::pair<idmap_type::iterator, bool> res_idmap = 
    idmap_.insert(idmap_type::value_type(uri, current_id_));
  assert(res_idmap.second);

  std::pair<urimap_type::iterator, bool> res_tokenmap = 
    urimap_.insert(urimap_type::value_type(current_id_, uri));
  assert(res_tokenmap.second);

  ++current_id_;
  return res_idmap.first->second;
}

const id_type namespace_map::get_namespace_id(const std::string &uri) const{
  idmap_type::const_iterator it = idmap_.find(uri);
  if (it == idmap_.end())
    return unregistered_token;

  return it->second;
}

const std::string &namespace_map::get_namespace_uri(const id_type id) const{
  urimap_type::const_iterator it = urimap_.find(id);
  if (it == urimap_.end())
    throw invalid_argument();
  return it->second;
}

//
//
//

void namespace_map::initialize() {
  if (urimap_.size() != 0)
    return;

  urimap_.insert(urimap_type::value_type(empty_token, ""));
  idmap_.insert(idmap_type::value_type("", empty_token));
}

void namespace_map::uninitialize() {
  urimap_.clear();
  idmap_.clear();
}


void prefix_map::assign_prefix(const std::string &prefix, const id_type id) {

  prefixmap_type::const_iterator itprefix = prefixmap_.find(id);
  idmap_type::const_iterator itid = idmap_.find(prefix);

  if ((itprefix != prefixmap_.end()) && (itid != idmap_.end())) {
    if (itprefix->second != prefix)
      throw invalid_argument();
    if (itid->second != id)
      throw invalid_argument();
  }
  else if ((itprefix != prefixmap_.end()) || (itid != idmap_.end()))
    throw invalid_argument();

  prefixmap_.insert(prefixmap_type::value_type(id, prefix));
  idmap_.insert(idmap_type::value_type(prefix, id));
}

const id_type prefix_map::get_prefix_id(const std::string &prefix) const{
  idmap_type::const_iterator it = idmap_.find(prefix);
  if (it != idmap_.end())
    return it->second;
  else
    return unregistered_token;
}

void prefix_map::clear_prefix(const std::string &prefix) {

  id_type id;

  idmap_type::iterator itid = idmap_.find(prefix);
  if (itid == idmap_.end()) 
    throw invalid_argument();

  id = itid->second;
  prefixmap_type::iterator itprefix = prefixmap_.find(id);

  if (itprefix == prefixmap_.end())
    throw invalid_argument();

  prefixmap_.erase(itprefix);
  idmap_.erase(itid);
}

const std::string &prefix_map::get_prefix(const id_type id) const{
  prefixmap_type::const_iterator it = prefixmap_.find(id);
  if (it == prefixmap_.end())
    throw invalid_argument();
  return it->second;
}

void prefix_map::initialize() {
  prefixmap_.clear();
  idmap_.clear();
}

void prefix_map::uninitialize() {
  prefixmap_.clear();
  idmap_.clear();
}

} // namespace aka2
