/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * PdbAtomInfoContainer.cpp
 *
 *  Created on: Dec 4, 2010
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include "CodePatterns/Assert.hpp"
//#include "CodePatterns/Log.hpp"
#include "CodePatterns/toString.hpp"
//#include "CodePatterns/Verbose.hpp"
#include "LinearAlgebra/Vector.hpp"
#include "PdbAtomInfoContainer.hpp"
PdbAtomInfoContainer::knownDataKeysMap PdbAtomInfoContainer::knownDataKeys;
bool PdbAtomInfoContainer::knownDataKeys_Filled = false;
PdbAtomInfoContainer::PdbAtomInfoContainer() :
  token("ATOM"),
  serial(0),
  name("-"),
  altLoc('0'),
  resName("-"),
  chainID('0'),
  resSeq(0),
  iCode(' '),
  occupancy(0.),
  tempFactor(0.),
  element(""),
  charge(0)
{
  if (!knownDataKeys_Filled)
    fillknownDataKeys();
}
PdbAtomInfoContainer::~PdbAtomInfoContainer()
{}
void PdbAtomInfoContainer::fillknownDataKeys()
{
  knownDataKeys[PdbKey::token] = "token";
  knownDataKeys[PdbKey::serial] = "serial";
  knownDataKeys[PdbKey::name] = "name";
  knownDataKeys[PdbKey::altLoc] = "altLoc";
  knownDataKeys[PdbKey::resName] = "resName";
  knownDataKeys[PdbKey::chainID] = "chainID";
  knownDataKeys[PdbKey::resSeq] = "resSeq";
  knownDataKeys[PdbKey::iCode] = "iCode";
  knownDataKeys[PdbKey::X] = "X";
  knownDataKeys[PdbKey::Y] = "Y";
  knownDataKeys[PdbKey::Z] = "Z";
  knownDataKeys[PdbKey::occupancy] = "occupancy";
  knownDataKeys[PdbKey::tempFactor] = "tempFactor";
  knownDataKeys[PdbKey::element] = "element";
  knownDataKeys[PdbKey::charge] = "charge";
  knownDataKeys_Filled = true;
}
void PdbAtomInfoContainer::clearknownDataKeys()
{
  knownDataKeys.clear();
  knownDataKeys_Filled = false;
}
void PdbAtomInfoContainer::set(const PdbKey::PdbDataKey key, std::string value)
{
  switch (key) {
    case PdbKey::token :
      ScanKey(token, value);
      break;
    case PdbKey::serial :
      ScanKey(serial, value);
      break;
    case PdbKey::name :
      ScanKey(name, value);
      break;
    case PdbKey::altLoc :
      ScanKey(altLoc, value);
      break;
    case PdbKey::resName :
      ScanKey(resName, value);
      break;
    case PdbKey::chainID :
      ScanKey(chainID, value);
      break;
    case PdbKey::resSeq :
      ScanKey(resSeq, value);
      break;
    case PdbKey::iCode :
      ScanKey(iCode, value);
      break;
    case PdbKey::X :
      ScanKey(XYZ[0], value);
      break;
    case PdbKey::Y :
      ScanKey(XYZ[1], value);
      break;
    case PdbKey::Z :
      ScanKey(XYZ[2], value);
      break;
    case PdbKey::occupancy :
      ScanKey(occupancy, value);
      break;
    case PdbKey::tempFactor :
      ScanKey(tempFactor, value);
      break;
    case PdbKey::element :
      ScanKey(element, value);
      break;
    case PdbKey::charge :
      ScanKey(charge, value);
      break;
    default :
      std::cout << "Unknown key: " << key << ", value: " << value << std::endl;
      break;
  }
}
template <>
std::string PdbAtomInfoContainer::get(const PdbKey::PdbDataKey key) const
{
  switch (key) {
    case PdbKey::token :
      return toString(token);
    case PdbKey::serial :
      return toString(serial);
    case PdbKey::name :
      return toString(name);
    case PdbKey::altLoc :
      return toString(altLoc);
    case PdbKey::resName :
      return toString(resName);
    case PdbKey::chainID :
      return toString(chainID);
    case PdbKey::resSeq :
      return toString(resSeq);
    case PdbKey::iCode :
      return toString(iCode);
    case PdbKey::X :
      return toString(XYZ[0]);
    case PdbKey::Y :
      return toString(XYZ[1]);
    case PdbKey::Z :
      return toString(XYZ[2]);
    case PdbKey::occupancy :
      return toString(occupancy);
    case PdbKey::tempFactor :
      return toString(tempFactor);
    case PdbKey::element :
      return toString(element);
    case PdbKey::charge :
      return toString(charge);
    default :
      std::cout << "Unknown key: " << key << std::endl;
      return "";
  }
}
template <>
int PdbAtomInfoContainer::get(const PdbKey::PdbDataKey key) const
{
  switch (key) {
    case PdbKey::serial :
      return serial;
    case PdbKey::resSeq :
      return resSeq;
    case PdbKey::charge :
      return charge;
    default :
      std::cout << "Unknown key or not presentable as int: " << key << std::endl;
      return 0;
  }
}
template <>
double PdbAtomInfoContainer::get(const PdbKey::PdbDataKey key) const
{
  switch (key) {
    case PdbKey::X :
      return XYZ[0];
    case PdbKey::Y :
      return XYZ[1];
    case PdbKey::Z :
      return XYZ[2];
    case PdbKey::occupancy :
      return occupancy;
    case PdbKey::tempFactor :
      return tempFactor;
    default :
      std::cout << "Unknown key or not presentable as double: " << key << std::endl;
      return 0.;
  }
}
const std::string& PdbAtomInfoContainer::getDataKey(PdbKey::PdbDataKey key) const
{
  knownDataKeysMap::const_iterator iter;
  iter = knownDataKeys.find(key);
  ASSERT(iter != knownDataKeys.end(),
      "PdbAtomInfoContainer::getDataKey() - unknown key "
      +toString(key)+" request, did someone add a key to PdbKey?");
  return iter->second;
}
std::ostream& operator<<(std::ostream &ost, const PdbAtomInfoContainer& m)
{
  ost << m.getDataKey(PdbKey::token) << "(" << m.get(PdbKey::token) <<") ";
  ost << m.getDataKey(PdbKey::serial) << "(" << m.get(PdbKey::serial) <<") ";
  ost << m.getDataKey(PdbKey::name) << "(" << m.get(PdbKey::name) <<") ";
  ost << m.getDataKey(PdbKey::altLoc) << "(" << m.get(PdbKey::altLoc) <<") ";
  ost << m.getDataKey(PdbKey::resName) << "(" << m.get(PdbKey::resName) <<") ";
  ost << m.getDataKey(PdbKey::chainID) << "(" << m.get(PdbKey::chainID) <<") ";
  ost << m.getDataKey(PdbKey::resSeq) << "(" << m.get(PdbKey::resSeq) <<") ";
  ost << m.getDataKey(PdbKey::iCode) << "(" << m.get(PdbKey::iCode) <<") ";
  ost << m.getDataKey(PdbKey::X) << "(" << m.get(PdbKey::X) <<") ";
  ost << m.getDataKey(PdbKey::Y) << "(" << m.get(PdbKey::Y) <<") ";
  ost << m.getDataKey(PdbKey::Z) << "(" << m.get(PdbKey::Z) <<") ";
  ost << m.getDataKey(PdbKey::occupancy) << "(" << m.get(PdbKey::occupancy) <<") ";
  ost << m.getDataKey(PdbKey::tempFactor) << "(" << m.get(PdbKey::tempFactor) <<") ";
  ost << m.getDataKey(PdbKey::element) << "(" << m.get(PdbKey::element) <<") ";
  ost << m.getDataKey(PdbKey::charge) << "(" << m.get(PdbKey::charge) <<") ";
  return ost;
}