//============================================================================
// Copyright 2016 ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//
//============================================================================

#include "MessageLabel.h"

#include <QHBoxLayout>
#include <QLabel>
#include <QMovie>
#include <QPainter>
#include <QProgressBar>
#include <QStyleOption>
#include <QToolButton>
#include <QVariant>
#include <QVBoxLayout>

#include "IconProvider.h"
#include "MvLog.h"
#include "MvQTheme.h"
#include "MvQStreamOper.h"

#include <map>
#include <cassert>

class MessageLabelData
{
public:
    MessageLabelData(QString iconPath, QString title, QColor bg, QColor border) :
        title_(title),
        bg_(bg.name()),
        border_(border.name())
    {
        int id = IconProvider::add(iconPath, iconPath);
        pix_ = IconProvider::pixmap(id, 16);
        pixSmall_ = IconProvider::pixmap(id, 12);
    }

    MessageLabelData() = default;

    QPixmap pix_;
    QPixmap pixSmall_;
    QString title_;
    QString bg_;
    QString border_;
};

static std::map<MessageLabel::Type, MessageLabelData> typeData;

MessageLabel::MessageLabel(QWidget* parent) :
    QWidget(parent),
    currentType_(NoType),
    showTypeTitle_(true),
    narrowMode_(false)
{
    // id for dynamic styling
    setProperty("_messageLabel", "1");

    if (typeData.empty()) {
        typeData[InfoType] = MessageLabelData(":/examiner/label_info.svg", "Info",
                                              MvQTheme::colour("message_info", "bg"),
                                              MvQTheme::colour("message_info", "border"));

        typeData[WarningType] = MessageLabelData(":/examiner/label_warning.svg", "Warning",
                                                 MvQTheme::colour("message_warning", "bg"),
                                                 MvQTheme::colour("message_warning", "border"));

        typeData[ErrorType] = MessageLabelData(":/examiner/label_error.svg", "Error",
                                               MvQTheme::colour("message_error", "bg"),
                                               MvQTheme::colour("message_error", "border"));

        typeData[TipType] = MessageLabelData(":/examiner/label_tip.svg", "Tip",
                                             MvQTheme::colour("message_tip", "bg"),
                                             MvQTheme::colour("message_tip", "border"));
    }

    pixLabel_ = new QLabel(this);
    pixLabel_->setAlignment(Qt::AlignCenter);

    msgLabel_ = new QLabel(this);
    msgLabel_->setWordWrap(true);
    msgLabel_->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);

    loadLabel_ = new QLabel(this);

    // progress widget
    progLabel_ = new QLabel(this);
    progBar_ = new QProgressBar(this);
    progWidget_ = new QWidget(this);
    auto* progLayout = new QHBoxLayout(progWidget_);
    progLayout->addWidget(progBar_);
    progLayout->addWidget(progLabel_);

    layout_ = new QHBoxLayout(this);
    layout_->setContentsMargins(2, 2, 2, 2);

    auto* loadLayout = new QVBoxLayout();
    loadLayout->addWidget(loadLabel_);
    loadLayout->addStretch(1);
    layout_->addLayout(loadLayout);

    auto* pixLayout = new QVBoxLayout();
    pixLayout->addWidget(pixLabel_);
    pixLayout->addStretch(1);
    layout_->addLayout(pixLayout);

    auto rightVb = new QVBoxLayout;
    rightVb->addWidget(msgLabel_);
    rightVb->addWidget(progWidget_);
    rightVb->addStretch(1);
    layout_->addLayout(rightVb, 1);

    stopLoadLabel();
    stopProgress();

    hide();
}

void MessageLabel::clear()
{
    msgLabel_->setText("");
    stopLoadLabel();
    stopProgress();
}

void MessageLabel::showInfo(QString msg)
{
    showMessage(InfoType, msg);
}

void MessageLabel::showWarning(QString msg)
{
    showMessage(WarningType, msg);
}

void MessageLabel::showError(QString msg)
{
    showMessage(ErrorType, msg);
}

void MessageLabel::showTip(QString msg)
{
    showMessage(TipType, msg);
}

void MessageLabel::showMessage(const Type& type, QString msg)
{
    auto it = typeData.find(type);
    assert(it != typeData.end());

    if (type != currentType_) {
        QString sh =
            "QWidget[_messageLabel=\"1\"] { \
				    background: " +
            it->second.bg_ +
            "; \
                    border: 1px solid " +
            it->second.border_ +
            "; \
                    border-radius: 0px;}";

        setStyleSheet(sh);

        MvLog().dbg() <<"STYLESHEET=" << sh;

        pixLabel_->setPixmap(((!narrowMode_) ? it->second.pix_ : it->second.pixSmall_));

        currentType_ = type;
    }

    QString s = msg;
    s.replace("\n", "<br>");
    if (showTypeTitle_)
        s = "<b>" + it->second.title_ + ": </b><br>" + s;

    msgLabel_->setText(s);

    show();
}

void MessageLabel::startLoadLabel()
{
    if (!loadLabel_->movie()) {
        auto* movie = new QMovie(":viewer/spinning_wheel.gif", QByteArray(), loadLabel_);
        loadLabel_->setMovie(movie);
    }
    loadLabel_->show();
    loadLabel_->movie()->start();
}


void MessageLabel::stopLoadLabel()
{
    if (loadLabel_->movie()) {
        loadLabel_->movie()->stop();
    }

    loadLabel_->hide();
}

void MessageLabel::startProgress(int max)
{
    Q_ASSERT(max >= 0 && max <= 100);
    progBar_->setRange(0, max);
    progWidget_->show();
}

void MessageLabel::stopProgress()
{
    progWidget_->hide();
    progLabel_->setText("");
    progBar_->setRange(0, 0);
}

void MessageLabel::progress(QString text, int value)
{
    Q_ASSERT(value >= 0 && value <= 100);

    if (progBar_->maximum() == 0)
        progBar_->setMaximum(100);

    progBar_->setValue(value);
    progLabel_->setText(text);

    // UserMessage::debug("MessageLabel::progress --> " + QString::number(value).toStdString() + "%");
}

void MessageLabel::setShowTypeTitle(bool b)
{
    if (showTypeTitle_ != b) {
        showTypeTitle_ = b;
    }
}

void MessageLabel::setNarrowMode(bool b)
{
    if (b == narrowMode_)
        return;

    narrowMode_ = b;

    /*if(!narrowMode_)
    {
        layout_->setContentsMargins(2,2,2,2);
    }
    else
    {
        layout_->setContentsMargins(2,0,2,0);
    }*/
}


void MessageLabel::showCustomButton(QString text)
{
    if (customButton_ == nullptr) {
        customButton_ = new QToolButton(this);
        layout_->addWidget(customButton_);
        connect(customButton_, SIGNAL(clicked()),
                this, SIGNAL(customButtonClicked()));

    }
    customButton_->setText(text);
    customButton_->show();
}

void MessageLabel::hideCustomButton()
{
    if (customButton_ != nullptr) {
        customButton_->hide();
    }
}


void MessageLabel::paintEvent(QPaintEvent*)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
