#include "LtrManagerEnv.h"

#include "MainWindow.h"
#include "ActionPlugin.h"
#include <QAction>
#include <QEvent>
#include "StatisticPanel/StatisticModel.h"

class LtrManagerEnv::ActionDescr {
public:
    ActionDescr(QAction *action, LtrManagerEnv::ActionType type, LtrManagerEnv::ActionGroup group) :
        m_act(action), m_type(type), m_group(group) {}

    LtrManagerEnv::ActionType type() const {return m_type;}
    LtrManagerEnv::ActionGroup group() const {return m_group;}

    QAction *action() const {return m_act;}

    void addPlugin(ActionPlugin *plugin) {m_plugins.append(plugin);}

    void updateStatus(LtrManagerEnv *env);
    void activate(LtrManagerEnv *env);
private:
    QAction *m_act;
    LtrManagerEnv::ActionType m_type;
    LtrManagerEnv::ActionGroup m_group;

    QList<ActionPlugin *> m_plugins;
};











LtrManagerEnv::LtrManagerEnv(QWidget *win) : QObject(win), m_curCon(0), m_curCrate(0),
    m_curSlot(StatisticModel::invalidSlot), m_win(win) {

    m_cratesModel = new LtrCratesModel(this);

    QAction *act;
    act = createAction(ActionTypeCrateConfig, ActionGroupCrateInstance);
    act = createAction(ActionTypeCrateSyncCtl, ActionGroupCrateInstance);
    act = createAction(ActionTypeCrateReset, ActionGroupCrateInstance);
    act = createAction(ActionTypeCrateBoot, ActionGroupCrateInstance);



    retranslate();
}


void LtrManagerEnv::retranslate() {
    action(ActionTypeCrateConfig)->setText(tr("Crate settings..."));
    action(ActionTypeCrateSyncCtl)->setText(tr("Crate sync control..."));
    action(ActionTypeCrateReset)->setText(tr("Crate reset"));
    action(ActionTypeCrateBoot)->setText(tr("Update crate firmware..."));
}

LtrManagerEnv::~LtrManagerEnv() {
    qDeleteAll(m_actionDescrs);
}

void LtrManagerEnv::registerActionPlugin(LtrManagerEnv::ActionType type, ActionPlugin *plugin) {
    ActionDescr *ret = actionDesc(type);
    if (ret) {
        ret->addPlugin(plugin);
    }
}

LtrManagerEnv::ActionDescr *LtrManagerEnv::actionDesc(LtrManagerEnv::ActionType type) const {
    ActionDescr *ret = 0;
    for (int i=0; (i < m_actionDescrs.size()) && !ret; i++) {
        if (m_actionDescrs[i]->type() == type)
            ret = m_actionDescrs[i];
    }
    return ret;
}

QAction *LtrManagerEnv::action(LtrManagerEnv::ActionType type) const {
    ActionDescr *ret = actionDesc(type);
    return ret ? ret->action() : 0;
}

QList<QAction *> LtrManagerEnv::actions(LtrManagerEnv::ActionGroup group) const {
    QList<QAction *> ret;
    for (int i=0; i < m_actionDescrs.size(); i++) {
        if (m_actionDescrs[i]->group() == group)
            ret.append(m_actionDescrs[i]->action());
    }
    return ret;
}


void LtrManagerEnv::crateSelectionChanged(QModelIndex current, QModelIndex previous) {
    m_cratesModel->getInfo(current, &m_curCon, &m_curCrate, &m_curSlot);
    foreach (ActionDescr *descr, m_actionDescrs) {
        descr->updateStatus(this);
    }
}



void LtrManagerEnv::onActionTriggered() {
    QAction *act = qobject_cast<QAction*>(sender());
    if (act) {
        for (int i=0; i < m_actionDescrs.size(); i++) {
            if (m_actionDescrs[i]->action() == act)
                m_actionDescrs[i]->activate(this);
        }
    }
}

QAction* LtrManagerEnv::createAction(LtrManagerEnv::ActionType type, LtrManagerEnv::ActionGroup group) {
    QAction *act = new QAction(this);
    act->setEnabled(false);
    m_actionDescrs.append(new ActionDescr(act, type, group));
    connect(act, SIGNAL(triggered()), this, SLOT(onActionTriggered()));
    return act;
}





void LtrManagerEnv::ActionDescr::updateStatus(LtrManagerEnv *env) {
    bool enabled = false;
    foreach (ActionPlugin *plugin, m_plugins) {
        if (plugin->actionEnabled(env, m_type)) {
            enabled = true;
            break;
        }
    }
    m_act->setEnabled(enabled);
}

void LtrManagerEnv::ActionDescr::activate(LtrManagerEnv *env) {
    foreach (ActionPlugin *plugin, m_plugins) {
        if (plugin->actionEnabled(env, m_type)) {
            plugin->actionActivate(env, m_type);
            /* Выходим по первому выполнению. Иначе может получится, что
             * за время выполнения события выбор сменился и стал активен крейт другого
             * типа и действие следующего плагина для него доступно и будет выполнено */
            break;
        }
    }
}
