#include <QDebug>
#include "logcategories.h"

#include "tablewidget.h"



tableWidget::tableWidget(QWidget *parent): QTableWidget(parent)
{
    menuActions.append(new QAction("Add Item"));
    menuActions.append(new QAction("Insert Item"));
    menuActions.append(new QAction("Clone Item"));
    menuActions.append(new QAction("Delete Item"));
}

void tableWidget::addItem()
{
    int row=this->rowCount();
    this->insertRow(this->rowCount());
    emit rowAdded(row);
}

void tableWidget::insertItem()
{
    int row=this->currentRow();
    this->insertRow(this->currentRow());
    emit rowAdded(row);
}

void tableWidget::cloneItem()
{
    this->setSortingEnabled(false);
    int row=this->currentRow(); // This will be the new row with the old one as row+1
    this->insertRow(this->currentRow());
    for (int i=0;i<this->columnCount();i++)
    {
        if (this->item(row+1,i) != NULL && dynamic_cast<QComboBox*>(this->item(row+1,i)) == nullptr) // Don't try to copy checkbox
            this->model()->setData(this->model()->index(row,i),this->item(row+1,i)->text());
    }
    emit rowAdded(row);
    this->setSortingEnabled(true);
}

void tableWidget::deleteItem()
{
    if (this->currentRow() < 0)
        return;
    emit rowDeleted(this->currentRow());
    emit rowValDeleted((this->item(this->currentRow(),1) == NULL) ? 0 : this->item(this->currentRow(),1)->text().toUInt());
    this->removeRow(this->currentRow());
}

void tableWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton && editingEnabled)
    {
        QMenu menu;

#if (QT_VERSION < QT_VERSION_CHECK(6,0,0))
        QAction *selectedAction = menu.exec(menuActions,event->globalPos());
#else
        QAction *selectedAction = menu.exec(menuActions,event->globalPosition().toPoint());
#endif


        if(selectedAction == menuActions[0])
        {
            addItem();
        }
        else if(selectedAction == menuActions[1])
        {
            insertItem();
        }
        else if( selectedAction == menuActions[2] )
        {
            cloneItem();
        }
        else if( selectedAction == menuActions[3] )
        {
            deleteItem();
        } else
        {
            emit menuAction(selectedAction,this->currentRow());
        }
    }
}


tableEditor::tableEditor(QString validExp, QObject *parent)
    : QItemDelegate(parent), validExp(validExp)
{
}

QWidget* tableEditor::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
    Q_UNUSED(index)
    Q_UNUSED(option)
    edit = new QLineEdit(parent);
    if (!validExp.isEmpty())
    {
        edit->setInputMask(validExp);
    }
    edit->setFrame(false);
    return edit ;
}


tableCombobox::tableCombobox(QAbstractItemModel* model, bool sort, QObject *parent)
    : QItemDelegate(parent), modelData(model)
{
    if (sort)
        modelData->sort(0);
}

QWidget* tableCombobox::createEditor(QWidget *parent, const   QStyleOptionViewItem &option, const QModelIndex &index) const {
    Q_UNUSED(index)
    Q_UNUSED(option)
    combo = new QComboBox(parent);

    QObject::connect(combo,SIGNAL(currentIndexChanged(int)),this,SLOT(setData(int)));
    combo->blockSignals(true);
    combo->setModel(modelData);

    combo->setFocusPolicy(Qt::StrongFocus);
    combo->setEditable(true);
    combo->setInsertPolicy(QComboBox::NoInsert);

    QSortFilterProxyModel* filter = new QSortFilterProxyModel(combo);
    filter->setFilterCaseSensitivity(Qt::CaseInsensitive);
    filter->setSourceModel(combo->model());

    QCompleter* completer = new QCompleter(filter,combo);
    completer->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
    combo->setCompleter(completer);
    QObject::connect(combo->lineEdit(),SIGNAL(textEdited(QString)),filter,SLOT(setFilterFixedString(QString)));

    comboValidator* valid = new comboValidator(combo);
    combo->lineEdit()->setValidator(valid);

    connect(combo->lineEdit(), &QLineEdit::returnPressed, combo->lineEdit(), [=]() {
        if (combo->findText(combo->lineEdit()->text(), Qt::MatchExactly) < 0)
        {
            combo->lineEdit()->setText(combo->itemText(0)); // Set to first entry in combobox.
        }
    });


    combo->blockSignals(false);
    return combo;
}

void tableCombobox::setEditorData(QWidget *editor, const QModelIndex &index) const {
    // update model widget
    Q_UNUSED(editor)
    combo->blockSignals(true);
    QString text = index.model()->data( index, Qt::DisplayRole ).toString();
    combo->setCurrentIndex(combo->findText(text,Qt::MatchFixedString));
    combo->blockSignals(false);
}

void tableCombobox::setModelData(QWidget *editor, QAbstractItemModel *model,   const QModelIndex &index) const {
    Q_UNUSED(editor)
    model->setData( index, combo->currentText() );
}

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

void tableCombobox::setData(int val)
{
    Q_UNUSED(val)

    if (combo != Q_NULLPTR) {
        emit commitData(combo);
    }
}


tableCheckbox::tableCheckbox(QObject *parent)
    : QItemDelegate(parent)
{

}

QWidget* tableCheckbox::createEditor(QWidget *parent, const   QStyleOptionViewItem &option, const QModelIndex &index) const {
    Q_UNUSED(index)
    Q_UNUSED(option)
    QCheckBox* checkBox = new QCheckBox(parent);
    return checkBox;
}

void tableCheckbox::setEditorData(QWidget *editor, const QModelIndex &index) const {
    // update model widget
    bool value = index.model()->data(index, Qt::EditRole).toBool();
    qDebug() << "Value:" << value;
    QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
    checkBox->setEnabled(value);
}

void tableCheckbox::setModelData(QWidget *editor, QAbstractItemModel *model,   const QModelIndex &index) const {
    // store edited model data to model
    QCheckBox* checkBox = static_cast<QCheckBox*>(editor);
    bool value = checkBox->isChecked();
    model->setData(index, value, Qt::EditRole);    
}

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