/*
 * 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 .
 */
/*
 * Menu.cpp
 *
 *  Created on: Dec 10, 2009
 *      Author: crueger
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include 
#include "Actions/ActionRegistry.hpp"
#include "Actions/Action.hpp"
#include "Actions/ActionTrait.hpp"
#include "Menu/Menu.hpp"
using namespace MoleCuilder;
/** Constructor of class Menu.
 * \param &_name name of menu
 */
Menu::Menu(const std::string &_name) :
  MenuInterface(_name),
  name(_name),
  TopPosition(0),
  LastItem(NoItem)
{}
/** Destructor of class Menu.
 *
 */
Menu::~Menu()
{
  DuplicatesList.clear();
}
/** Initialiser for class Menu.
 * Fills menus with items.
 */
void Menu::init()
{
  populate();
  populateActions();
}
/** Initializing function.
 * Inserts Menus and Actions obtained from MenuDescription and
 * ActionRegistry.
 */
void Menu::populate()
{
  // go through all menus and create them
  bool CompleteFlag = false;  // indicates whether all menus have been added
  bool PossibleMissingFlag = false; // indicates whether a separator is missing
  while (!CompleteFlag) {
    CompleteFlag = true;
    PossibleMissingFlag = false;
    for(MenuDescription::const_iterator iter = MenuDescription::getInstance().getBeginIter();
        iter != MenuDescription::getInstance().getEndIter();
        ++iter) {
      // skip when already present
      if (!isPresent(iter->first)) {
        // have some short refs to infos
        const std::string &MenuName = iter->first;
        const std::string &TopName = iter->second.first;
        const int &MenuPosition = iter->second.second;
//        std::cout << "MenuName is " << MenuName
//            << ", TopName is " << TopName
//            << " and Position is " << MenuPosition
//            << std::endl;
        // does it belong to us?
        if (TopName == name) {
          if (MenuPosition-1 == TopPosition) {
            Menu::addSubmenu(MenuName, MenuPosition);
            CompleteFlag = false;
          }
          // is there a menuposition specified that we have not reached yet?
          if (MenuPosition-1 > TopPosition)
            PossibleMissingFlag = true;
        }
      }
    }
    if (PossibleMissingFlag && (CompleteFlag)) {
      Menu::addSeparator();
      CompleteFlag = false; // pass once more as there should be a menu to come
    }
  }
}
/** Fills this menu with all Actions that belong to it.
 */
void Menu::populateActions()
{
  // go through all actions and add those belonging to this menu
  ActionRegistry &AR = ActionRegistry::getInstance();
  for (ActionRegistry::const_iterator iter = AR.getBeginIter();
      iter != AR.getEndIter();
      ++iter) {
    const std::string &MenuName = iter->second->Traits.getMenuName();
    if (MenuName == name) {
      const std::string &ActionName = iter->first;
      Menu::addAction(ActionName);
    }
  }
}
void Menu::addAction(const std::string &ActionName)
{
  LastItem = ActionItem;
  addActionItem(ActionName, ActionName);
}
void Menu::addSeparator()
{
//  std::cout << "Creating separator at position " << TopPosition << std::endl;
  ASSERT( LastItem != SeparatorItem,
      "Menu::populate() - adding another separator after a separator!");
  LastItem = SeparatorItem;
  addSeparatorItem();
  TopPosition++;
}
void Menu::addSubmenu(const std::string &MenuName, const int MenuPosition)
{
//  std::cout << "Creating top-level menu " << MenuName
//      << " at position " << TopPosition << std::endl;
  ASSERT (!isPresent(MenuName),
      "Menu::addSubmenu() - trying to add menu "+MenuName+" with already present token!");
  addSubmenuItem(MenuName, MenuDescription::getInstance().getDescription(MenuName));
  DuplicatesList.insert(MenuName);
  LastItem = MenuItem;
  TopPosition = MenuPosition;
}
bool Menu::isPresent(const std::string &token)
{
  return (DuplicatesList.find(token) != DuplicatesList.end());
}