/***********************************************************************
 *                                                                     *
 * Copyright 2016  Lorenzo Porta (Vindex17) <vindex17@outlook.it>      *
 *                                                                     *
 * 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 3 of      *
 * the License or any later version accepted by the membership of      *
 * KDE e.V. (or its successor approved by the membership of KDE        *
 * e.V.), which shall act as a proxy defined in Section 14 of          *
 * version 3 of the license.                                           *
 *                                                                     *
 * 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, see <http://www.gnu.org/licenses/> *
 *                                                                     *
 ***********************************************************************/


#include "exclusionwidget.hxx"
#include "exclusionwidget.moc"

#include <KIO/Global>
#include <KListWidgetSearchLine>
#include <KLocalizedString>
#include <KMessageBox>
#include <KStandardGuiItem>
#include <QFileDialog>
#include <QInputDialog>
#include <QPushButton>
#include <QVBoxLayout>


ExclusionWidget::ExclusionWidget() : QGroupBox(i18nc("@title:group", "Files and directories to be excluded"))
{
    // Setup widgets
    QPushButton* const add_files_button = new QPushButton(KStandardGuiItem::add().icon(), i18nc("@action:button", "Add files"));
    connect(add_files_button, &QPushButton::clicked, this, &ExclusionWidget::add_files, Qt::DirectConnection);
    QPushButton* const add_directory_button = new QPushButton(QIcon::fromTheme(QStringLiteral("folder-add")), i18nc("@action:button", "Add directory"));
    connect(add_directory_button, &QPushButton::clicked, this, &ExclusionWidget::add_directory, Qt::DirectConnection);
    QPushButton* const add_pcre_button = new QPushButton(QIcon::fromTheme(QStringLiteral("tool_text")), i18nc("@action:button", "Add PCRE"));
    connect(add_pcre_button, &QPushButton::clicked, this, &ExclusionWidget::add_pcre, Qt::DirectConnection);
    const auto &remove_ksgi = KStandardGuiItem::remove();
    QPushButton* const remove_items_button = new QPushButton(remove_ksgi.icon(), remove_ksgi.text());
    connect(remove_items_button, &QPushButton::clicked, this, &ExclusionWidget::remove_items, Qt::DirectConnection);
    const auto &clear_ksgi = KStandardGuiItem::clear();
    QPushButton* const clear_button = new QPushButton(clear_ksgi.icon(), clear_ksgi.text());
    connect(clear_button, &QPushButton::clicked, this, &ExclusionWidget::clear, Qt::DirectConnection);
    KListWidgetSearchLine* const klistwidgetsearchline = new KListWidgetSearchLine(0, listwidget);
    klistwidgetsearchline->setPlaceholderText(i18nc("@label:textbox", "Search"));
    klistwidgetsearchline->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
    QHBoxLayout* const buttons_layout = new QHBoxLayout;
    buttons_layout->addWidget(add_files_button);
    buttons_layout->addWidget(add_directory_button);
    buttons_layout->addWidget(add_pcre_button);
    buttons_layout->addWidget(remove_items_button);
    buttons_layout->addWidget(clear_button);
    buttons_layout->addWidget(klistwidgetsearchline);
    // ↓
    listwidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
    // ↓
    QVBoxLayout* const this_layout = new QVBoxLayout(this);
    this_layout->addLayout(buttons_layout);
    this_layout->addWidget(listwidget);
}


void ExclusionWidget::restore(const QList<QString>&& pcre_pattern_list, const QList<QUrl>&& url_list)
{
    clear();
    for (const auto &pcre_pattern : pcre_pattern_list)
        pcre_hash.insert(new QListWidgetItem(QIcon::fromTheme(QStringLiteral("tool_text")), pcre_pattern, listwidget), QRegularExpression(pcre_pattern, QRegularExpression::OptimizeOnFirstUsageOption));
    for (const auto &url : url_list)
        urls_to_exclude_hash.insert(new QListWidgetItem(icon_for(url), url.toDisplayString(URL_DISPLAY_FORMAT), listwidget), url);
}


void ExclusionWidget::add_directory()
{
    const auto &url = QFileDialog::getExistingDirectoryUrl(this, i18nc("@title:window", "Select a directory"), QUrl::fromLocalFile(QDir::homePath())).adjusted(QUrl::NormalizePathSegments);
    if (Q_LIKELY(url.isEmpty() == false))
        urls_to_exclude_hash.insert(new QListWidgetItem(icon_for(url), url.toDisplayString(URL_DISPLAY_FORMAT), listwidget), url);
}


void ExclusionWidget::clear()
{
    listwidget->clear();
    pcre_hash.clear();
    urls_to_exclude_hash.clear();
}


void ExclusionWidget::add_files()
{
    const auto &url_list = QFileDialog::getOpenFileUrls(this, i18nc("@title:window", "Select one or more files"), QUrl::fromLocalFile(QDir::homePath()),
                                                        QStringLiteral("*"), 0, QFileDialog::DontConfirmOverwrite | QFileDialog::DontResolveSymlinks);
    for (const auto &current_url : url_list) {
        const auto &adjusted_url = current_url.adjusted(QUrl::NormalizePathSegments);
        urls_to_exclude_hash.insert(new QListWidgetItem(icon_for(adjusted_url), adjusted_url.toDisplayString(URL_DISPLAY_FORMAT), listwidget), adjusted_url);
    }
}


void ExclusionWidget::add_pcre()
{
    const auto &text = QInputDialog::getText(this, QString(), i18nc("@label:textbox", "Perl-compatible regular expression:"));
    if (Q_LIKELY(text.isEmpty() == false)) {
        QRegularExpression pcre(text, QRegularExpression::OptimizeOnFirstUsageOption);
        if (pcre.isValid())
            pcre_hash.insert(new QListWidgetItem(QIcon::fromTheme(QStringLiteral("tool_text")), text, listwidget), pcre);
        else
            KMessageBox::sorry(parentWidget(), xi18nc("@info", "Invalid PCRE: <message>%1</message>", pcre.errorString()));
    }
}


void ExclusionWidget::remove_items()
{
    for (const auto &current_lwi : listwidget->selectedItems()) {
        Q_ASSERT(urls_to_exclude_hash.contains(current_lwi) || pcre_hash.contains(current_lwi));
        if (urls_to_exclude_hash.remove(current_lwi) < 1)
            pcre_hash.remove(current_lwi);
        delete current_lwi;
    }
}
