/*********
*
* This file is part of BibleTime's source code, http://www.bibletime.info/.
*
* Copyright 1999-2011 by the BibleTime developers.
* The BibleTime source code is licensed under the GNU General Public License version 2.0.
*
**********/

#include "frontend/displaywindow/btmodulechooserbutton.h"

#include <QDebug>
#include <QHash>
#include <QMenu>
#include <QString>
#include <QToolButton>
#include <QToolTip>
#include "backend/config/cbtconfig.h"
#include "backend/managers/cswordbackend.h"
#include "frontend/displaywindow/btmodulechooserbar.h"
#include "util/cresmgr.h"
#include "util/directory.h"


BtModuleChooserButton::BtModuleChooserButton(BtModuleChooserBar *parent, CSwordModuleInfo::ModuleType mtype)
        : QToolButton(parent),
        m_moduleType(mtype),
        m_popup(0) {
    setPopupMode(QToolButton::InstantPopup);
}

void BtModuleChooserButton::recreateMenu(QStringList newModulesToUse, QString thisModule, int newIndex, int leftLikeModules) {
    populateMenu();
    updateMenu(newModulesToUse, thisModule, newIndex, leftLikeModules);
}

const QString BtModuleChooserButton::iconName() {
    switch (m_moduleType) {
        case CSwordModuleInfo::Bible:
            return (m_hasModule) ? CResMgr::modules::bible::icon_unlocked : CResMgr::modules::bible::icon_add;
        case CSwordModuleInfo::Commentary:
            return (m_hasModule) ? CResMgr::modules::commentary::icon_unlocked : CResMgr::modules::commentary::icon_add;
        case CSwordModuleInfo::Lexicon:
            return m_hasModule ? CResMgr::modules::lexicon::icon_unlocked : CResMgr::modules::lexicon::icon_add;
        case CSwordModuleInfo::GenericBook:
            return m_hasModule ? CResMgr::modules::book::icon_unlocked : CResMgr::modules::book::icon_add;
        default: //return as default the bible icon
            return CResMgr::modules::bible::icon_unlocked;
    }
}

void BtModuleChooserButton::updateMenu(QStringList newModulesToUse, QString thisModule, int newIndex, int leftLikeModules) {
    m_id = newIndex;

    // create the menu if it doesn't exist
    if (!m_popup)
        populateMenu();

    m_module = thisModule;
    m_hasModule = thisModule.isEmpty() ? false : true;
    namespace DU = util::directory;

    //All items are iterated and the state is changed properly
    QListIterator<QMenu*> it(m_submenus);
    while (it.hasNext()) {
        QMenu* popup = it.next();
        foreach (QAction* a, popup->actions()) {
            a->setChecked( (a->text() == thisModule) ? true : false );
            a->setDisabled( newModulesToUse.contains(a->text()) ? true : false );
        }
    }
    m_noneAction->setChecked(m_hasModule ? false : true);
    setIcon(DU::getIcon(iconName()));

    if (m_hasModule) {
        setToolTip( QString(tr("Select a work [%1]")).arg(m_module) );
    }
    else {
        setToolTip( tr("Select an additional work") );
    }
    bool disableNone = false;
    if (newModulesToUse.count() == 1 ||
        (newIndex == 0 && leftLikeModules == 1))
        disableNone = true;
    m_noneAction->setDisabled(disableNone);

    // Disable non-Bible categories on first button
    if (m_moduleType == CSwordModuleInfo::Bible && m_id == 0) {
        QList<QAction*> actions = m_popup->actions();
        for (int i=0; i<actions.count(); i++) {
            QAction* action = actions.at(i);
            QString text = action->text();
            if (text != QObject::tr("Bibles")) {
                action->setDisabled(true);
            }
        }
    }
}

/** Is called after a module was selected in the popup */
void BtModuleChooserButton::moduleChosen( QAction* action ) {
    if (action->text() == tr("NONE")) { // note: this is for m_popup, the toplevel!
        if (m_hasModule) {
            qDebug() << "remove module" << m_id;
            emit sigModuleRemove(m_id);
            return;
        }
        else {
            // nothing else is done but the item must be set to checked
            // lest it change to unchecked
            action->setChecked(true);
        }
    }
    else {
        if (!m_hasModule) {
            emit sigModuleAdd(m_id + 1, action->text());
            return;
        }
        emit sigModuleReplace(m_id, action->text());
    }
}


void BtModuleChooserButton::populateMenu() {
    qDeleteAll(m_submenus);
    m_submenus.clear();
    delete m_popup;
    m_popup = new QMenu(this);

    m_noneAction = m_popup->addAction(tr("NONE"));
    m_noneAction->setCheckable(true);
    if (m_module.isEmpty()) m_noneAction->setChecked(true);

    m_popup->addSeparator();
    connect(m_popup, SIGNAL(triggered(QAction*)), this, SLOT(moduleChosen(QAction*)));
    setMenu(m_popup);


    // ******* Add languages and modules ********

    // Filters: add only non-hidden and right type
    BTModuleTreeItem::HiddenOff hiddenFilter;
    QList<BTModuleTreeItem::Filter*> filters;
    if (!CBTConfig::get(CBTConfig::bookshelfShowHidden)) {
        filters.append(&hiddenFilter);
    }
    TypeFilter typeFilter(m_moduleType);
    filters.append(&typeFilter);

    if (m_moduleType == CSwordModuleInfo::Bible) {
      BTModuleTreeItem root(filters, BTModuleTreeItem::CatLangMod);
        QList<BTModuleTreeItem::Filter*> filters2;
        if (!CBTConfig::get(CBTConfig::bookshelfShowHidden)) {
            filters2.append(&hiddenFilter);
        }
        TypeFilter typeFilter2(CSwordModuleInfo::Commentary);
        filters2.append(&typeFilter2);
        root.add_items(filters2);
        // add all items recursively
        addItemToMenu(&root, m_popup);
    }
    else {
        BTModuleTreeItem root(filters, BTModuleTreeItem::LangMod);
        addItemToMenu(&root, m_popup);
    }
}

void BtModuleChooserButton::addItemToMenu(BTModuleTreeItem* item, QMenu* menu) {
    foreach (BTModuleTreeItem* i, item->children()) {

        if (i->type() == BTModuleTreeItem::Language ||
            i->type() == BTModuleTreeItem::Category ) {
            // argument menu was m_popup, create and add a new lang menu to it
            QMenu* langMenu = new QMenu(i->text(), this);
            menu->addMenu(langMenu);
            m_submenus.append(langMenu);
            // add the module items to the lang menu
            addItemToMenu(i, langMenu);
        }
        else {
            // item must be module, create and add it to the lang menu
            QString name(i->text());
            QAction* modItem = new QAction(name, menu);
            modItem->setCheckable(true);
            menu->addAction(modItem);
        }
    }
}
