/*
    SPDX-FileCopyrightText: 2007 Joris Guisson <joris.guisson@gmail.com>
    SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "groupview.h"

#include <QAction>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QHeaderView>
#include <QInputDialog>
#include <QMenu>
#include <QTreeWidgetItemIterator>

#include <KActionCollection>
#include <KConfigGroup>
#include <KLocalizedString>
#include <KMessageBox>

#include "core.h"
#include "grouppolicydlg.h"
#include "gui.h"
#include "view/view.h"
#include <groups/group.h>
#include <groups/groupmanager.h>
#include <groups/torrentgroup.h>
#include <interfaces/torrentactivityinterface.h>
#include <interfaces/torrentinterface.h>
#include <util/log.h>

using namespace bt;

namespace kt
{
GroupView::GroupView(GroupManager *gman, View *view, Core *core, GUI *gui, QWidget *parent)
    : QTreeView(parent)
    , gui(gui)
    , core(core)
    , view(view)
    , gman(gman)
    , model(new GroupViewModel(gman, view, parent))
{
    setRootIsDecorated(false);
    setContextMenuPolicy(Qt::CustomContextMenu);
    setModel(model);
    header()->hide();

    connect(this, &GroupView::clicked, this, &GroupView::onItemClicked);
    connect(this, &GroupView::customContextMenuRequested, this, &GroupView::showContextMenu);
    connect(this, &GroupView::currentGroupChanged, view, &View::onCurrentGroupChanged);
    connect(gman, &GroupManager::customGroupChanged, this, &GroupView::updateGroupCount);

    setAcceptDrops(true);
    setDropIndicatorShown(true);
    setDragDropMode(QAbstractItemView::DropOnly);
}

GroupView::~GroupView()
{
}

void GroupView::setupActions(KActionCollection *col)
{
    open_in_new_tab = new QAction(QIcon::fromTheme(QStringLiteral("list-add")), i18n("Open In New Tab"), this);
    connect(open_in_new_tab, &QAction::triggered, this, &GroupView::openInNewTab);
    col->addAction(QStringLiteral("open_in_new_tab"), open_in_new_tab);

    new_group = new QAction(QIcon::fromTheme(QStringLiteral("document-new")), i18n("New Group"), this);
    connect(new_group, &QAction::triggered, this, &GroupView::addGroup);
    col->addAction(QStringLiteral("new_group"), new_group);

    edit_group = new QAction(QIcon::fromTheme(QStringLiteral("insert-text")), i18n("Edit Name"), this);
    connect(edit_group, &QAction::triggered, this, &GroupView::editGroupName);
    col->addAction(QStringLiteral("edit_group_name"), edit_group);

    remove_group = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Remove Group"), this);
    connect(remove_group, &QAction::triggered, this, &GroupView::removeGroup);
    col->addAction(QStringLiteral("remove_group"), remove_group);

    edit_group_policy = new QAction(QIcon::fromTheme(QStringLiteral("preferences-other")), i18n("Group Policy"), this);
    connect(edit_group_policy, &QAction::triggered, this, &GroupView::editGroupPolicy);
    col->addAction(QStringLiteral("edit_group_policy"), edit_group_policy);
}

void GroupView::addGroup()
{
    addNewGroup();
}

Group *GroupView::addNewGroup()
{
    bool ok = false;
    QString name = QInputDialog::getText(this, QString(), i18n("Please enter the group name."), QLineEdit::Normal, QString(), &ok);

    if (name.isEmpty() || name.length() == 0 || !ok)
        return nullptr;

    if (gman->find(name)) {
        KMessageBox::error(this, i18n("The group %1 already exists.", name));
        return nullptr;
    }

    Group *g = gman->newGroup(name);
    gman->saveGroups();
    return g;
}

void GroupView::removeGroup()
{
    Group *g = model->groupForIndex(selectionModel()->currentIndex());
    if (g) {
        gman->removeGroup(g);
        gman->saveGroups();
    }
}

void GroupView::editGroupName()
{
    edit(selectionModel()->currentIndex());
}

void GroupView::showContextMenu(const QPoint &p)
{
    Group *g = model->groupForIndex(selectionModel()->currentIndex());

    bool enable = g && gman->canRemove(g);
    edit_group->setEnabled(enable);
    remove_group->setEnabled(enable);
    edit_group_policy->setEnabled(enable);

    open_in_new_tab->setEnabled(g != nullptr);

    QMenu *menu = gui->getTorrentActivity()->part()->menu(QStringLiteral("GroupsMenu"));
    if (menu)
        menu->popup(viewport()->mapToGlobal(p));
}

void GroupView::onItemClicked(const QModelIndex &index)
{
    Group *g = model->groupForIndex(index);
    if (g)
        currentGroupChanged(g);
}

void GroupView::editGroupPolicy()
{
    Group *g = model->groupForIndex(selectionModel()->currentIndex());
    if (g) {
        GroupPolicyDlg dlg(g, this);
        if (dlg.exec() == QDialog::Accepted)
            gman->saveGroups();
    }
}

void GroupView::saveState(KSharedConfigPtr cfg)
{
    KConfigGroup g = cfg->group("GroupView");
    g.writeEntry("expanded", model->expandedGroups(this));
    g.writeEntry("visible", isVisible());
}

void GroupView::loadState(KSharedConfigPtr cfg)
{
    KConfigGroup g = cfg->group("GroupView");
    QStringList default_expanded;
    default_expanded << QStringLiteral("/all") << QStringLiteral("/all/downloads") << QStringLiteral("/all/uploads") << QStringLiteral("/all/active")
                     << QStringLiteral("/all/passive") << QStringLiteral("/all/custom");
    QStringList slist = g.readEntry("expanded", default_expanded);
    model->expandGroups(this, slist);
    setVisible(g.readEntry("visible", true));
    expand(model->index(0, 0));
}

void GroupView::keyPressEvent(QKeyEvent *event)
{
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
        onItemClicked(selectionModel()->currentIndex());
    else
        QTreeView::keyPressEvent(event);
}

void GroupView::updateGroupCount()
{
    model->updateGroupCount(model->index(0, 0));
}

void GroupView::openInNewTab()
{
    Group *g = model->groupForIndex(selectionModel()->currentIndex());
    if (g)
        openTab(g);
}
}
