/***************************** LICENSE START ***********************************

 Copyright 2014 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQRequestPanelLine.h"

#include <QApplication>
#include <QDebug>
#include <QFrame>
#include <QLabel>
#include <QStyle>
#include <QToolButton>

#include "MvQRequestPanelHelp.h"

#include "LineFactory.h"
#include "MvIconParameter.h"
#include "RequestPanel.h"
#include "MvQMethods.h"
#include "MvQTheme.h"

MvQRequestPanelLine::MvQRequestPanelLine(RequestPanel& owner, const MvIconParameter& param, bool buildLine) :
    RequestPanelItem(owner, param),
    defaultTb_(nullptr),
    helpTb_(nullptr),
    helper_(nullptr),
    parentWidget_(owner.parentWidget())
{
    if (!buildLine)
        return;

    RequestPanel* parentLayout = &owner_;

    //Toggle to indicate default/non-default settings
    defaultTb_ = new QToolButton(parentWidget_);
    defaultTb_->setObjectName(QString::fromUtf8("guiItemDefaultTb"));
    defaultTb_->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));
    defaultTb_->setMaximumSize(QSize(20, 20));
    defaultTb_->setToolTip(tr("Reset parameter"));
    //defaultTb_->setIconSize(QSize(10,10));
    defaultTb_->setAutoRaise(true);
    defaultTb_->setIcon(QPixmap(":/desktop/reset_lineEditor.svg"));
    //defaultTb_->setIcon(QPixmap(":/desktop/link.svg"));

    connect(defaultTb_, SIGNAL(clicked(bool)),
            this, SLOT(slotChangeToDefault(bool)));

    //name label
    name_           = QString::fromStdString(param.beautifiedName());
    QString nameStr = name_;
    if (const char* w_text = param.warning_text()) {
        nameStr += MvQ::formatText(" " + QString(w_text), MvQTheme::colour("iconeditor", "warning_pen"));
    }

    nameLabel_ = new QLabel(nameStr, parentWidget_);
    nameLabel_->setProperty("lineEdit", "1");
    const char* help_text = param.help_text();
    if (help_text)
        nameLabel_->setToolTip("<font>" + QString(help_text) + "</font>");

    row_ = parentLayout->rowCount();
    parentLayout->addWidget(defaultTb_, row_, DefaultColumn);
    parentLayout->addWidget(nameLabel_, row_, NameColumn);

    defaultTb_->setVisible(false);
    //defaultTb_->setEnabled(false);
}

MvQRequestPanelLine::~MvQRequestPanelLine()
{
    if (helper_)
        delete helper_;
}


MvQRequestPanelLine* MvQRequestPanelLine::build(RequestPanel& owner, const MvIconParameter& param)
{
    MvQRequestPanelLine* p = LineFactory::create(owner, param);
    p->buildHelper();
    //p->init(w);
    return p;
}

void MvQRequestPanelLine::buildHelper()
{
    if (helper_)
        return;

    helper_ = MvQRequestPanelHelp::build(owner_, param_);

    if (!helper_)
        return;

    MvRequest helpReq = param_.interfaceRequest();

    //Toolbuton to show/hide help widget or launch dialog helper
    helpTb_ = new QToolButton(parentWidget_);
    //helpTb_->setObjectName(QString::fromUtf8("guiItemDefaultTb"));

    //Set helper icon
    if (helper_->dialog()) {
        helpTb_->setIcon(helper_->dialogIcon());
        if (helper_->useLargeDialogIcon())
            helpTb_->setMaximumSize(QSize(20, 20));
        else
            helpTb_->setMaximumSize(QSize(16, 16));
    }
    else {
        QIcon ic;
        ic.addPixmap(QPixmap(":/desktop/expand_left.svg"), QIcon::Normal, QIcon::On);
        ic.addPixmap(QPixmap(":/desktop/expand_right.svg"), QIcon::Normal, QIcon::Off);
        helpTb_->setIcon(ic);
        helpTb_->setMaximumSize(QSize(16, 16));
        helpTb_->setCheckable(true);
        helpTb_->setChecked(false);
    }

    if (const char* ttip = helpReq("help_tooltip")) {
        helpTb_->setToolTip(QString(ttip));
    }

    helpTb_->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum));

    RequestPanel* parentLayout = &owner_;
    parentLayout->addWidget(helpTb_, row_, ExpandColumn);

    if (helper_->dialog()) {
        connect(helpTb_, SIGNAL(clicked(bool)),
                this, SLOT(slotStarHelpDialog(bool)));
    }
    else {
        parentLayout->addWidget(helper_->widget(), row_ + 1, DefaultColumn, 1, 4);
        helper_->widget()->setVisible(false);
        // this is not set for the css but for the painter
        helper_->widget()->setProperty("paintAsHelper", "1");

        connect(helpTb_, SIGNAL(toggled(bool)),
                this, SLOT(slotHelpTbToggled(bool)));

        connect(helpTb_, SIGNAL(toggled(bool)),
                this, SLOT(slotHelperOpened(bool)));

        connect(helper_, SIGNAL(edited(const std::vector<std::string>&)),
                this, SLOT(slotHelperEdited(const std::vector<std::string>&)));

        connect(helper_, SIGNAL(edited(QStringList, QVector<bool>)),
                this, SLOT(slotHelperEdited(QStringList, QVector<bool>)));

        connect(helper_, SIGNAL(editConfirmed()),
                this, SLOT(slotHelperEditConfirmed()));
    }
}

void MvQRequestPanelLine::setLineVisible(bool st, bool forced)
{
    if (st != lineVisible_ || forced) {
        lineVisible_ = st;
        for (int i = 0; i < owner_.columnCount(); i++) {
            QLayoutItem* item = owner_.itemAtPosition(row_, i);
            if (item) {
                if (QWidget* w = item->widget()) {
                    if (w == defaultTb_ && lineVisible_) {
                        w->setVisible(mark_);
                    }
                    else {
                        w->setVisible(lineVisible_);
                    }
                }
            }
        }
        if (helper_ && !helper_->dialog()) {
            if (helpTb_->isChecked()) {
                helper_->widget()->setVisible(lineVisible_);
            }
            else {
                helper_->widget()->setVisible(false);
            }
        }
    }
}

void MvQRequestPanelLine::setLineEnabled(bool st)
{
    if (helper_ && !helper_->dialog()) {
        helper_->widget()->setEnabled(st);
    }

    for (int i = 0; i < owner_.columnCount(); i++) {
        QLayoutItem* item = owner_.itemAtPosition(row_, i);
        if (item) {
            if (QWidget* w = item->widget()) {
                if (w != defaultTb_) {
                    w->setEnabled(st);
                }
            }
        }
    }
}

void MvQRequestPanelLine::setVisibleByTemporary(bool st)
{
    if (param_.hiddenInTemporary() && st) {
        visibleByTemporary_ = false;
        adjustState();
    }
}

void MvQRequestPanelLine::setVisibleByFilter(bool st)
{
    visibleByFilter_ = st;
    adjustState();
}

void MvQRequestPanelLine::adjustDisabled()
{
    if (gray_)
        adjustState(true);
}

// indicates disabled state
void MvQRequestPanelLine::gray(bool g)
{
    if (gray_ != g) {
        gray_ = g;
        adjustState();
    }
}

// indicates that a non-default value is set
void MvQRequestPanelLine::mark(bool g)
{
    mark_ = g;
    adjustState(true);

    owner_.updateParentWidget();
}

void MvQRequestPanelLine::adjustState(bool forced)
{
    if (!visibleByTemporary_) {
        setLineVisible(false, forced);
    } else if (!visibleByFilter_) {
        setLineVisible(false, forced);
    }
    else {
        setLineEnabled(!gray_);
        if (!gray_) {
            setLineVisible(true, forced);
        }
        else {
            setLineVisible(owner_.showDisabledItems(), forced);
        }
    }
}

void MvQRequestPanelLine::slotChangeToDefault(bool)
{
    //This will reset the request and call update on all the items
    owner_.setToDefault(this);
}

void MvQRequestPanelLine::slotStarHelpDialog(bool)
{
    if (helper_)
        helper_->start();
}

void MvQRequestPanelLine::slotHelpTbToggled(bool b)
{
    helper_->widget()->setVisible(b);

    //We need to immediately repaint the background of the main gridlayout.
    //This was the only method to make it work!!
    owner_.updateParentWidget();
    qApp->processEvents();
}

bool MvQRequestPanelLine::hasDefaultTb()
{
    if (defaultTb_)
        return defaultTb_->isVisible();

    return false;
}
