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

 Copyright 2012 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 <QAbstractItemView>
#include <QApplication>
#include <QBrush>
#include <QCheckBox>
#include <QColor>
#include <QDebug>
#include <QPainter>
#include <QStringList>
#include <QStylePainter>

#include "MvQCheckBoxCombo.h"


MvQCheckBoxComboDelegate::MvQCheckBoxComboDelegate(QWidget* parent) :
    QStyledItemDelegate(parent)
{
}

void MvQCheckBoxComboDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
                                     const QModelIndex& index) const
{
    if (option.state & QStyle::State_Selected)
        painter->fillRect(option.rect, option.palette.highlight());

    // Get item status
    bool status = index.data(Qt::UserRole).toBool();

    // Get item label
    QString text = index.data(Qt::DisplayRole).toString();

    // Fill style options with item data
    const QStyle* style = QApplication::style();

    QStyleOptionButton opt;

    opt.state |= status ? QStyle::State_On : QStyle::State_Off;
    opt.state |= QStyle::State_Enabled;
    opt.text = text;
    opt.rect = option.rect;

    // Draw item data as CheckBox
    style->drawControl(QStyle::CE_CheckBox, &opt, painter);
}

QWidget* MvQCheckBoxComboDelegate::createEditor(QWidget* parent,
                                                const QStyleOptionViewItem&,
                                                const QModelIndex&) const
{
    // Create check box as our editor
    auto* editor = new QCheckBox(parent);

    editor->setFocusPolicy(Qt::StrongFocus);

    connect(editor, SIGNAL(stateChanged(int)),
            this, SLOT(slotCheckBoxStateChanged(int)));
    return editor;
}

void MvQCheckBoxComboDelegate::slotCheckBoxStateChanged(int /*checked*/)
{
    commmitAndCloseEditor();
}

void MvQCheckBoxComboDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
    auto* myEditor = static_cast<QCheckBox*>(editor);

    myEditor->setText(index.data(Qt::DisplayRole).toString());
    myEditor->setChecked(index.data(Qt::UserRole).toBool());
}


void MvQCheckBoxComboDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
    //	qDebug() << "setModelData";
    // get the value from the editor (CheckBox)

    auto* myEditor = static_cast<QCheckBox*>(editor);

    bool value = myEditor->isChecked();

    // set model data

    QMap<int, QVariant> data;

    data.insert(Qt::DisplayRole, myEditor->text());
    data.insert(Qt::UserRole, value);

    model->setItemData(index, data);

    //	qDebug() << "dataChanged";
    emit dataChanged();
}

void MvQCheckBoxComboDelegate::updateEditorGeometry(QWidget* editor,
                                                    const QStyleOptionViewItem& option, const QModelIndex&) const
{
    editor->setGeometry(option.rect);
}

void MvQCheckBoxComboDelegate::commmitAndCloseEditor()
{
    auto* editor = static_cast<QCheckBox*>(sender());
    //	qDebug() << "commitdata";
    emit commitData(editor);

    // emit closeEditor(slider);
}


MvQCheckBoxCombo::MvQCheckBoxCombo(QWidget* widget) :
    QComboBox(widget)
{
    // set delegate items view
    auto* delegate = new MvQCheckBoxComboDelegate(this);

    view()->setItemDelegate(delegate);

    // Enable editing on items view
    view()->setEditTriggers(QAbstractItemView::CurrentChanged);

    // set "CheckBoxList::eventFilter" as event filter for items view
    view()->viewport()->installEventFilter(this);

    view()->setAlternatingRowColors(true);

    connect(delegate, SIGNAL(dataChanged()),
            this, SLOT(repaint()));

    connect(delegate, SIGNAL(dataChanged()),
            this, SIGNAL(selectionChanged()));
}

MvQCheckBoxCombo::~MvQCheckBoxCombo() = default;

bool MvQCheckBoxCombo::eventFilter(QObject* object, QEvent* event)
{
    // don't close items view after we release the mouse button
    // by simple eating MouseButtonRelease in viewport of items view

    if (event->type() == QEvent::MouseButtonRelease && object == view()->viewport()) {
        return true;
    }
    return QComboBox::eventFilter(object, event);
}

void MvQCheckBoxCombo::paintEvent(QPaintEvent*)
{
    //   	qDebug() << "repaint";

    QStylePainter painter(this);

    painter.setPen(palette().color(QPalette::Text));

    // draw the combobox frame, focusrect and selected etc.

    QStyleOptionComboBox opt;

    initStyleOption(&opt);

    QString str;
    for (int i = 0; i < count(); i++) {
        QModelIndex index = model()->index(i, 0);
        if (model()->data(index, Qt::UserRole).toBool() == true) {
            if (str.size() != 0) {
                str.append("/");
            }

            str.append(model()->data(index, Qt::DisplayRole).toString());
        }
    }
    // if no display text been set , use "..." as default
    if (str.size() > 0)
        opt.currentText = str;
    else

        opt.currentText = "...";

    painter.drawComplexControl(QStyle::CC_ComboBox, opt);

    // draw the icon and text
    painter.drawControl(QStyle::CE_ComboBoxLabel, opt);
}

QStringList MvQCheckBoxCombo::getSelectedValues()
{
    QStringList str;
    for (int i = 0; i < count(); i++) {
        QModelIndex index = model()->index(i, 0);
        if (model()->data(index, Qt::UserRole).toBool() == true)
            str.append(model()->data(index, Qt::DisplayRole).toString());
    }
    return str;
}
