/*
 *   This file is part of Dianara
 *   Copyright 2012-2019  JanKusanagi JRR <jancoding@gmx.com>
 *
 *   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, write to the
 *   Free Software Foundation, Inc.,
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .
 */

#include "filtereditor.h"

FilterEditor::FilterEditor(FilterChecker *filterChecker,
                           QWidget *parent) : QWidget(parent)
{
    m_filterChecker = filterChecker;

    this->setWindowTitle(tr("Filter Editor") + " - Dianara");
    this->setWindowIcon(QIcon::fromTheme("view-filter",
                                         QIcon(":/images/button-filter.png")));
    this->setWindowFlags(Qt::Dialog);
    this->setWindowModality(Qt::ApplicationModal);
    this->setMinimumSize(520, 440);

    QSettings settings;
    QSize savedWindowsize = settings.value("FilterEditor/filterWindowSize")
                                    .toSize();
    if (savedWindowsize.isValid())
    {
        this->resize(savedWindowsize);
    }


    m_ruleTemplateString = tr("%1 if %2 contains: %3",
                              "This explains a filter rule, like: "
                              "Hide if Author ID contains JohnDoe");

    QFont explanationFont;
    explanationFont.setPointSize(explanationFont.pointSize() - 1);

    m_explanationLabel = new QLabel(tr("Here you can set some rules for hiding or "
                                       "highlighting stuff. "
                                       "You can filter by content, author "
                                       "or application.\n\n"
                                       "For instance, you can filter out messages posted by "
                                       "the application Open Farm Game, or which contain the "
                                       "word NSFW in the message. You could also highlight "
                                       "messages that contain your name.")
                                    + "\n",
                                    this);
    m_explanationLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
    m_explanationLabel->setWordWrap(true);
    m_explanationLabel->setFont(explanationFont);


    m_actionTypeComboBox = new QComboBox(this);
    m_actionTypeComboBox->addItem(QIcon::fromTheme("edit-delete",
                                                   QIcon(":/images/button-delete.png")),
                                  tr("Hide"));
    m_actionTypeComboBox->addItem(QIcon::fromTheme("format-fill-color",
                                                   QIcon(":/images/button-online.png")),
                                  tr("Highlight"));
    m_actionTypeComboBox->setCurrentIndex(1); // #2 option (highlight) as default

    m_filterTypeComboBox = new QComboBox(this);
    m_filterTypeComboBox->addItem(QIcon::fromTheme("accessories-text-editor",
                                                   QIcon(":/images/button-edit.png")),
                                  tr("Post Contents"));
    m_filterTypeComboBox->addItem(QIcon::fromTheme("user-identity",
                                                   QIcon(":/images/no-avatar.png")),
                                  tr("Author ID"));
    m_filterTypeComboBox->addItem(QIcon::fromTheme("applications-other",
                                                   QIcon(":/images/button-configure.png")),
                                  tr("Application"));
    m_filterTypeComboBox->addItem(QIcon::fromTheme("accessories-text-editor",
                                                   QIcon(":/images/button-edit.png")),
                                  tr("Activity Description"));

    m_filterWordsLineEdit = new QLineEdit(this);
    m_filterWordsLineEdit->setPlaceholderText(tr("Keywords..."));
    m_filterWordsLineEdit->setClearButtonEnabled(true);

    m_addFilterButton = new QPushButton(QIcon::fromTheme("list-add",
                                                         QIcon(":/images/list-add.png")),
                                        tr("&Add Filter"),
                                        this);
    m_addFilterButton->setDisabled(true);
    connect(m_addFilterButton, &QAbstractButton::clicked,
            this, &FilterEditor::addFilter);
    connect(m_filterWordsLineEdit, &QLineEdit::returnPressed,
            this, &FilterEditor::addFilter);
    connect(m_filterWordsLineEdit, &QLineEdit::textChanged,
            this, &FilterEditor::onFilterTextChanged);



    m_filtersListWidget = new QListWidget(this);
    m_filtersListWidget->setToolTip(tr("Filters in use"));
    m_filtersListWidget->setDragDropMode(QAbstractItemView::InternalMove);


    m_removeFilterButton = new QPushButton(QIcon::fromTheme("list-remove",
                                                            QIcon(":/images/list-remove.png")),
                                           tr("&Remove Selected Filter"),
                                           this);
    m_removeFilterButton->setDisabled(true);
    connect(m_removeFilterButton, &QAbstractButton::clicked,
            this, &FilterEditor::removeFilter);
    connect(m_filtersListWidget, &QListWidget::currentRowChanged,
            this, &FilterEditor::onFilterRowChanged);


    m_saveButton = new QPushButton(QIcon::fromTheme("document-save",
                                                    QIcon(":/images/button-save.png")),
                                   tr("&Save Filters"),
                                   this);
    connect(m_saveButton, &QAbstractButton::clicked,
            this, &FilterEditor::saveFilters);

    m_cancelButton = new QPushButton(QIcon::fromTheme("dialog-cancel",
                                                      QIcon(":/images/button-cancel.png")),
                                     tr("&Cancel"),
                                     this);
    connect(m_cancelButton, &QAbstractButton::clicked,
            this, &QWidget::hide);

    m_bottomButtonBox = new QDialogButtonBox(this);
    m_bottomButtonBox->addButton(m_saveButton,   QDialogButtonBox::AcceptRole);
    m_bottomButtonBox->addButton(m_cancelButton, QDialogButtonBox::RejectRole);


    m_closeAction = new QAction(this);
    m_closeAction->setShortcut(QKeySequence(Qt::Key_Escape));
    connect(m_closeAction, &QAction::triggered,
            this, &QWidget::hide);
    this->addAction(m_closeAction);


    // Layout
    m_topLayout = new QHBoxLayout();
    m_topLayout->addWidget(m_actionTypeComboBox);
    m_topLayout->addSpacing(2);
    m_topLayout->addWidget(new QLabel(tr("if"), this));
    m_topLayout->addSpacing(2);
    m_topLayout->addWidget(m_filterTypeComboBox);
    m_topLayout->addSpacing(2);
    m_topLayout->addWidget(new QLabel(tr("contains"), this));
    m_topLayout->addSpacing(2);
    m_topLayout->addWidget(m_filterWordsLineEdit, 1);
    m_topLayout->addSpacing(8);
    m_topLayout->addWidget(m_addFilterButton);

    m_newFilterGroupBox = new QGroupBox(tr("&New Filter"), this);
    m_newFilterGroupBox->setLayout(m_topLayout);

    m_middleLayout = new QVBoxLayout();
    m_middleLayout->addWidget(m_filtersListWidget);
    m_middleLayout->addWidget(m_removeFilterButton, 0, Qt::AlignRight);

    m_currentFiltersGroupBox = new QGroupBox(tr("C&urrent Filters"), this);
    m_currentFiltersGroupBox->setLayout(m_middleLayout);


    m_mainLayout = new QVBoxLayout();
    m_mainLayout->addWidget(m_explanationLabel);
    m_mainLayout->addSpacing(4);
    m_mainLayout->addWidget(m_newFilterGroupBox);
    m_mainLayout->addSpacing(2);
    m_mainLayout->addWidget(m_currentFiltersGroupBox);
    m_mainLayout->addSpacing(8);
    m_mainLayout->addWidget(m_bottomButtonBox);
    this->setLayout(m_mainLayout);


    loadFilters();

    qDebug() << "FilterEditor created";
}


FilterEditor::~FilterEditor()
{
    qDebug() << "FilterEditor destroyed";
}


void FilterEditor::loadFilters()
{
    QSettings settings;

    QVariantList filtersList = settings.value("Filters/currentFilters").toList();

    foreach (const QVariant filterItem, filtersList)
    {
        int actionType = filterItem.toMap().value("action").toInt();
        int filterType = filterItem.toMap().value("type").toInt();
        QString filterWords = filterItem.toMap().value("text").toString();

        QVariantMap itemMap;
        itemMap.insert("action", actionType);
        itemMap.insert("type",   filterType);
        itemMap.insert("text",   filterWords);

        QListWidgetItem *item;
        item = new QListWidgetItem(m_ruleTemplateString
                                   .arg(m_actionTypeComboBox->itemText(actionType))
                                   .arg("'" + m_filterTypeComboBox->itemText(filterType) + "'")
                                   .arg("'" + filterWords + "'"));
        // Note: Don't mess with spaces around the ruleString parameters,
        // since the structure is different in other languages

        item->setData(Qt::UserRole, itemMap);

        m_filtersListWidget->addItem(item);
    }

    // Let the FilterChecker know
    m_filterChecker->setFilters(filtersList);
}



/****************************************************************************/
/********************************* SLOTS ************************************/
/****************************************************************************/



void FilterEditor::onFilterTextChanged(QString text)
{
    m_addFilterButton->setDisabled(text.isEmpty());
}


void FilterEditor::onFilterRowChanged(int row)
{
    m_removeFilterButton->setEnabled(row != -1);
}



void FilterEditor::addFilter()
{
    const QString words = m_filterWordsLineEdit->text().trimmed();
    if (words.isEmpty())
    {
        return;
    }

    QVariantMap itemMap;
    itemMap.insert("action", m_actionTypeComboBox->currentIndex());
    itemMap.insert("type",   m_filterTypeComboBox->currentIndex());
    itemMap.insert("text",   words);

    QListWidgetItem *item;
    item = new QListWidgetItem(m_ruleTemplateString
                               .arg(m_actionTypeComboBox->currentText())
                               .arg("'" + m_filterTypeComboBox->currentText() + "'")
                               .arg("'" + words + "'"));
    // Just as in loadFilters(), don't mess with spaces around the parameters
    item->setData(Qt::UserRole, itemMap);

    m_filtersListWidget->addItem(item);
    m_filtersListWidget->setCurrentRow(m_filtersListWidget->count() - 1);


    m_filterWordsLineEdit->clear();
}


void FilterEditor::removeFilter()
{
    int selectedFilter = m_filtersListWidget->currentRow();
    qDebug() << "FilterEditor::removeFilter()" << selectedFilter;

    if (selectedFilter != -1)
    {
        QListWidgetItem *removedItem = m_filtersListWidget->takeItem(selectedFilter);
        delete removedItem;
    }
}


void FilterEditor::saveFilters()
{
    qDebug() << "FilterEditor::saveFilters()";

    QVariantList filtersList;

    for (int counter = 0; counter != m_filtersListWidget->count(); ++counter)
    {
        QListWidgetItem *item = m_filtersListWidget->item(counter);
        filtersList.append(item->data(Qt::UserRole)); // data() holds a QVariantMap with the filter
    }

    qDebug() << "Filters list: " << filtersList;

    QSettings settings;
    settings.setValue("Filters/currentFilters", filtersList);

    // Send to the FilterChecker too
    m_filterChecker->setFilters(filtersList);

    this->hide();
}



//////////////////////////////////////////////////////////////////////////////
/////////////////////////////// PROTECTED ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////



void FilterEditor::closeEvent(QCloseEvent *event)
{
    this->hide();
    event->ignore();
}


void FilterEditor::hideEvent(QHideEvent *event)
{
    QSettings settings;
    settings.setValue("FilterEditor/filterWindowSize", this->size());

    event->accept();
}
