/*
 * ahcformdlg.cpp - Ad-Hoc Command Form Dialog
 * Copyright (C) 2005  Remko Troncon
 *
 * This program 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.
 *
 * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "ahcformdlg.h"

#include "ahcexecutetask.h"
#include "ahcommand.h"
#include "busywidget.h"
#include "psiaccount.h"
#include "xdata_widget.h"
#include "xmpp_client.h"

#include <QLabel>
#include <QLayout>
#include <QPushButton>
#include <QScrollArea>

AHCFormDlg::AHCFormDlg(PsiCon *psi, const AHCommand &r, const Jid &receiver, XMPP::Client *client, bool final) :
    QDialog(nullptr), _psi(psi), _pb_prev(nullptr), _pb_next(nullptr), _pb_complete(nullptr), _pb_cancel(nullptr),
    _xdata(nullptr), _receiver(receiver), _client(client)
{
    _ui.setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose);

    // Save node
    node_      = r.node();
    sessionId_ = r.sessionId();

    _ui.lb_note->setText(r.note().text);
    _ui.lb_note->setVisible(r.hasNote());

    _ui.lb_instructions->setText(r.data().instructions());
    _ui.lb_instructions->setVisible(!r.data().instructions().isEmpty());

    // XData form
    _xdata = new XDataWidget(_psi, this, _client, receiver);
    _xdata->setForm(r.data());
    //_xdata->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    _xdata->layout()->setSizeConstraint(QLayout::SetFixedSize);
    _ui.scrollArea->setWidget(_xdata);
    if (!r.hasData() && (r.hasNote() || !r.data().instructions().isEmpty()))
        _ui.scrollArea->setVisible(false);

    _ui.busy->setVisible(!final);

    if (!final) {
        if (r.actions().empty()) {
            // Single stage dialog
            _pb_complete = _ui.buttonBox->addButton(tr("Finish"), QDialogButtonBox::AcceptRole);
            connect(_pb_complete, SIGNAL(clicked()), SLOT(doExecute()));
        } else {
            // Multi-stage dialog

            // Previous
            _pb_prev = _ui.buttonBox->addButton(tr("Previous"), QDialogButtonBox::ActionRole);
            if (r.actions().contains(AHCommand::Prev)) {
                if (r.defaultAction() == AHCommand::Prev) {
                    _pb_prev->setDefault(true);
                    _pb_prev->setFocus();
                }
                connect(_pb_prev, SIGNAL(clicked()), SLOT(doPrev()));
                _pb_prev->setEnabled(true);
            } else {
                _pb_prev->setEnabled(false);
            }

            // Next
            _pb_next = _ui.buttonBox->addButton(tr("Next"), QDialogButtonBox::ActionRole);
            if (r.actions().contains(AHCommand::Next)) {
                if (r.defaultAction() == AHCommand::Next) {
                    connect(_pb_next, SIGNAL(clicked()), SLOT(doExecute()));
                    _pb_next->setDefault(true);
                    _pb_next->setFocus();
                } else {
                    connect(_pb_next, SIGNAL(clicked()), SLOT(doNext()));
                }
                _pb_next->setEnabled(true);
            } else {
                _pb_next->setEnabled(false);
            }

            // Complete
            _pb_complete = _ui.buttonBox->addButton(tr("Finish"), QDialogButtonBox::AcceptRole);
            if (r.actions().contains(AHCommand::Complete)) {
                if (r.defaultAction() == AHCommand::Complete) {
                    connect(_pb_complete, SIGNAL(clicked()), SLOT(doExecute()));
                    _pb_complete->setDefault(true);
                    _pb_complete->setFocus();
                } else {
                    connect(_pb_complete, SIGNAL(clicked()), SLOT(doComplete()));
                }
                _pb_complete->setEnabled(true);
            } else {
                _pb_complete->setEnabled(false);
            }
        }

        _pb_cancel = _ui.buttonBox->addButton(QDialogButtonBox::Cancel);
        connect(_pb_cancel, SIGNAL(clicked()), SLOT(doCancel()));
    } else {
        _pb_complete = _ui.buttonBox->addButton(QDialogButtonBox::Ok);
        connect(_pb_complete, SIGNAL(clicked()), SLOT(close()));
    }

    if (!r.data().title().isEmpty()) {
        setWindowTitle(QString("%1 (%2)").arg(r.data().title(), receiver.full()));
    } else {
        setWindowTitle(QString("%1").arg(receiver.full()));
    }

    adjustSize();
    show();
    setParent(nullptr);
}

void AHCFormDlg::doPrev()
{
    _ui.busy->start();
    AHCExecuteTask *t
        = new AHCExecuteTask(_receiver, AHCommand(node_, data(), sessionId_, AHCommand::Prev), _client->rootTask());
    connect(t, SIGNAL(finished()), SLOT(commandExecuted()));
    t->go(true);
}

void AHCFormDlg::doNext()
{
    _ui.busy->start();
    AHCExecuteTask *t
        = new AHCExecuteTask(_receiver, AHCommand(node_, data(), sessionId_, AHCommand::Next), _client->rootTask());
    connect(t, SIGNAL(finished()), SLOT(commandExecuted()));
    t->go(true);
}

void AHCFormDlg::doExecute()
{
    _ui.busy->start();
    AHCExecuteTask *t = new AHCExecuteTask(_receiver, AHCommand(node_, data(), sessionId_), _client->rootTask());
    connect(t, SIGNAL(finished()), SLOT(commandExecuted()));
    t->go(true);
}

void AHCFormDlg::doComplete()
{
    _ui.busy->start();
    AHCExecuteTask *t
        = new AHCExecuteTask(_receiver, AHCommand(node_, data(), sessionId_, AHCommand::Complete), _client->rootTask());
    connect(t, SIGNAL(finished()), SLOT(commandExecuted()));
    t->go(true);
}

void AHCFormDlg::doCancel()
{
    _ui.busy->start();
    AHCExecuteTask *t
        = new AHCExecuteTask(_receiver, AHCommand(node_, sessionId_, AHCommand::Cancel), _client->rootTask());
    connect(t, SIGNAL(finished()), SLOT(commandExecuted()));
    t->go(true);
}

void AHCFormDlg::commandExecuted()
{
    _ui.busy->stop();
    AHCExecuteTask *t = dynamic_cast<AHCExecuteTask *>(sender());
    if (t && t->hasCommandPayload()) {
        _xdata->setForm(t->resultCommand().data());
    } else {
        close();
    }
}

XData AHCFormDlg::data() const
{
    XData x;
    x.setFields(_xdata->fields());
    x.setType(XData::Data_Submit);
    return x;
}
