/*
 * 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 .
 */
/*
 * FormatParser_common_common.cpp
 *
 *  Created on: Mar 1, 2010
 *      Author: metzler
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
//#include "CodePatterns/MemDebug.hpp"
#include 
#include "CodePatterns/Observer/Notification.hpp"
#include "World.hpp"
#include "ChangeTracker.hpp"
#include "FormatParser_common.hpp"
using namespace std;
/**
 * Constructor.
 */
FormatParser_common::FormatParser_common(FormatParser_Parameters *_parameters) :
  Observer("FormatParser_common"),
  saveStream(NULL)
{
  parameters = _parameters;
  ChangeTracker::getInstance().signOn(this);
  World::getInstance().signOn(this, World::AtomInserted);
  World::getInstance().signOn(this, World::AtomRemoved);
}
/**
 * Destructor.
 */
FormatParser_common::~FormatParser_common() 
{
  ChangeTracker::getInstance().signOff(this);
  World::getInstance().signOff(this, World::AtomInserted);
  World::getInstance().signOff(this, World::AtomRemoved);
  if (parameters != NULL)
    delete parameters;
  // clear id translation maps
  LocaltoGobalIdMap.clear();
  GlobaltoLocalIdMap.clear();
  // flush stream properly (is maintained in FormatParserStorage)
  if (saveStream != NULL) {
    saveStream->flush();
    saveStream = NULL;
  }
}
/**
 * Update operation which can be invoked by the observable (which should be the
 * change tracker here).
 */
void FormatParser_common::update(Observable *publisher) {
  if (saveStream != NULL) { // only store when a saveStream is given
    std::vector atoms = const_cast(World::getInstance()).
        getAllAtoms();
    save(saveStream, atoms);
  }
}
/**
 * With this, each format parser is informed about specific changes in the World.
 */
void FormatParser_common::recieveNotification(Observable *publisher, Notification_ptr notification) {
  switch (notification->getChannelNo()) {
    case World::AtomInserted:
      AtomInserted(World::getInstance().lastChangedAtomId());
      break;
    case World::AtomRemoved:
      AtomRemoved(World::getInstance().lastChangedAtomId());
      break;
    default:
      ASSERT(0,
          "FormatParser_common::recieveNotification() - unknown notification "
          +toString(notification->getChannelNo())+" received.");
      break;
  }
}
/**
 * The observable can tell when it dies.
 */
void FormatParser_common::subjectKilled(Observable *publisher) {}
/**
 * Sets the output stream for save, so the save() method can be invoked on update
 * automatically.
 *
 * \param ostream where to save the World's state
 */
void FormatParser_common::setOstream(ostream* output)
{
  saveStream = output;
}
/** Function to be called when beginning to parse a new file.
 *
 * Resets internal translation maps.
 *
 */
void FormatParser_common::resetIdAssociations()
{
  LocaltoGobalIdMap.clear();
  GlobaltoLocalIdMap.clear();
}
/** Installs an association between a local id from a parsed file and the
 * global, unique one.
 *
 * @param local local atom id
 * @param global global atom id
 */
void FormatParser_common::associateLocaltoGlobalId(const int local, const int global)
{
  ASSERT(LocaltoGobalIdMap.count(local) == 0,
      "FormatParser_common::associateLocaltoGlobalId() - local id "
      +toString(local)+" is already contained.");
  ASSERT(GlobaltoLocalIdMap.count(global) == 0,
      "FormatParser_common::associateLocaltoGlobalId() - global id "
      +toString(global)+" is already contained.");
  LocaltoGobalIdMap[local] = global;
  GlobaltoLocalIdMap[global] = local;
}
/** Getter for the global id to a given \a local one.
 *
 * @param local local atom id
 * @return global atom id, -1 if unknown
 */
int FormatParser_common::getGlobalId(const int local) const
{
  IdtoIdMap::const_iterator iter = LocaltoGobalIdMap.find(local);
  if(iter == LocaltoGobalIdMap.end())
    return -1;
  return iter->second;
}
/** Getter for the local id to a given \a global one.
 *
 * @param global global atom id
 * @return local atom id, -1 if unknown
 */
int FormatParser_common::getLocalId(const int global) const
{
  IdtoIdMap::const_iterator iter = GlobaltoLocalIdMap.find(global);
  if(iter == GlobaltoLocalIdMap.end())
    return -1;
  return iter->second;
}