/*
 * 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 .
 */
/*
 * OptionRegistry.cpp
 *
 *  Created on: Oct 26, 2010
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include 
#include "Actions/Action.hpp"
#include "Actions/ActionQueue.hpp"
#include "Actions/ActionTrait.hpp"
#include "Actions/OptionRegistry.hpp"
#include "Actions/OptionTrait.hpp"
#include "CodePatterns/Singleton_impl.hpp"
#include "CodePatterns/Registry_impl.hpp"
using namespace MoleCuilder;
/** Constructor for class OptionRegistry.
 */
OptionRegistry::OptionRegistry()
{}
/** Destructor for class OptionRegistry.
 */
OptionRegistry::~OptionRegistry()
{}
/** Just passes on call to Registry::getByName().
 * \param name name of Option
 * \return pointer to Option's type
 */
const OptionTrait* OptionRegistry::getOptionByName(const std::string name) const
{
  return const_cast(getByName(name));
}
/** Initializes options from ActionRegistries contents.
 * Just goes through all Action's and adds their options.
 */
//void OptionRegistry::Init()
//{
//  ActionQueue &AQ = ActionQueue::getInstance();
//  ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
//  for (ActionQueue::ActionTokens_t::const_iterator actioniter = tokens.begin();
//      actioniter != tokens.end();
//      ++actioniter) {
//    const ActionTrait& currentTrait = AQ.getActionsTrait(*actioniter);
//    for (ActionTrait::options_const_iterator optioniter = currentTrait.getBeginIter();
//        optioniter != currentTrait.getEndIter();
//        ++optioniter) {
//      // wrap option in a shared_ptr to have it exist till and automatically removed at end of code
//      std::string const &OptionName = optioniter->first;
//      std::type_info const &typeDesired = *(currentTrait.getOptionType(OptionName));
//      if (isOptionPresentByName(OptionName)) {
//        std::type_info const &typePresent = *(getOptionByName(OptionName)->getType());
//        ASSERT( typeDesired == typePresent,
//            "OptionRegistry::Init() - Two options with same token do not have the same type!");
//      } else {
//        registerInstance(new Option(OptionName, &typeDesired));
//      }
//    }
//  }
//}
/** checking that each of the Actions' options has the same (and present) type in the OptionRegistry.
 * We use ASSERT
 */
void OptionRegistry::ConsistencyCheck()
{
  ActionQueue &AQ = ActionQueue::getInstance();
  ActionQueue::ActionTokens_t tokens = AQ.getListOfActions();
  for (ActionQueue::ActionTokens_t::const_iterator actioniter = tokens.begin();
      actioniter != tokens.end();
      ++actioniter) {
    const ActionTrait& currentTrait = AQ.getActionsTrait(*actioniter);
    for (ActionTrait::options_const_iterator optioniter = currentTrait.getBeginIter();
        optioniter != currentTrait.getEndIter();
        ++optioniter) {
#ifndef NDEBUG
      std::string const &OptionName = optioniter->first;
      std::type_info const &typeDesired = *(currentTrait.getOption(OptionName).getType());
      std::type_info const &typePresent = *(getOptionByName(OptionName)->getType());
#endif
      ASSERT( isOptionPresentByName(OptionName),
          "ConsistencyCheck() - option token "+OptionName+" not contained in OptionRegistry");
      ASSERT( typeDesired == typePresent,
          "ConsistencyCheck() - Two options -- "+toString(typeDesired.name())
          +" and "+toString(typePresent.name())+" -- with same token do not have the same type!");
    }
  }
};
/** Just passes on call to Registry::isPresentByName().
 * \param name name of Option
 * \return true - Option instance present, false - not
 */
bool OptionRegistry::isOptionPresentByName(const std::string name) const
{
  return isPresentByName(name);
}
CONSTRUCT_SINGLETON(OptionRegistry)
CONSTRUCT_REGISTRY(OptionTrait)