/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  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 .
 */
/*
 * LinkedCell_Model_changeModel.cpp
 *
 *  Created on: Dec 20, 2011
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include "LinkedCell_Model_changeModel.hpp"
#include "CodePatterns/Log.hpp"
#include "CodePatterns/toString.hpp"
/** Constructor of LinkedCell_Model::changeModel.
 *
 */
LinkedCell::LinkedCell_Model::changeModel::changeModel(const double distance) :
    Observable(std::string("LinkedCell_Model("+toString(distance)+")::changeModel"))
{}
/** Destructor of LinkedCell_Model::changeModel.
 *
 */
LinkedCell::LinkedCell_Model::changeModel::~changeModel()
{
  // remove all remaining updates in the queue
  for (UpdateQueueMap::iterator iter = queue.begin();
      !queue.empty();
      iter = queue.begin()) {
    delete iter->second;
    queue.erase(iter);
  }
}
/** Adds an Update instance to the internal queue.
 *
 * @param Walker node which is the update object
 * @param _updateMethod bound function (to LinkedCell_Model instance) of the update function
 */
void LinkedCell::LinkedCell_Model::changeModel::addUpdate(
    const TesselPoint *Walker,
    const LinkedCell_Model::Update::PriorityLevel priority,
    boost::function _updateMethod
    )
{
  UpdateQueueMap::iterator iter = queue.find(Walker);
  if (iter != queue.end()) {
    if(iter->second->getPriority() >= priority) {
      // replace present update with new one
      OBSERVE;
      delete iter->second;
      iter->second = new Update(_updateMethod, Walker, priority);
    } else {
      LOG(2, "INFO: Rejecting update for LinkedCell_Model as higher prioritized one is present.");
    }
  } else {
    // insert new update
    LOG(2, "INFO: Placing new update into queue for LinkedCell_Model.");
    OBSERVE;
    queue.insert( std::make_pair(Walker, new Update(_updateMethod, Walker, priority)) );
  }
}
/** Empties changeModel::queue by performing all update functions.
 *
 */
void LinkedCell::LinkedCell_Model::changeModel::performUpdates()
{
  LOG(2, "INFO: Performing "+toString(queue.size())+" updates on LinkedCell_Model.");
  for (UpdateQueueMap::iterator iter = queue.begin();
      !queue.empty();
      iter = queue.begin()) {
    LOG(2, "INFO: Performing update ...");
    // perform update
    (*iter->second)();
    // remove update
    delete iter->second;
    queue.erase(iter);
  }
}