/*
  Copyright (c) 2014 Christian Mollekopf <mollekopf@kolabsys.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 "tagwidgets.h"
#include <KJob>

#include <QHBoxLayout>
#include <AkonadiCore/Tag>
#include <AkonadiCore/TagFetchJob>
#include <AkonadiCore/TagFetchScope>
#include <AkonadiCore/TagCreateJob>
#include <AkonadiWidgets/TagWidget>
#include <AkonadiCore/TagModel>
#include <AkonadiCore/Monitor>
#include "libkdepimakonadi_debug.h"

using namespace KPIM;

class KPIM::TagWidgetPrivate
{
public:
    TagWidgetPrivate()
    {
    }

    Akonadi::TagWidget *mTagWidget = nullptr;
    Akonadi::Tag::List mTagList;
    QStringList mCachedTagNames;
};

TagWidget::TagWidget(QWidget *parent)
    : QWidget(parent)
    , d(new KPIM::TagWidgetPrivate)
{
    d->mTagWidget = new Akonadi::TagWidget(this);
    connect(d->mTagWidget, &Akonadi::TagWidget::selectionChanged, this, &TagWidget::onSelectionChanged);
    QHBoxLayout *l = new QHBoxLayout(this);
    l->setContentsMargins(0, 0, 0, 0);
    l->setSpacing(0);
    l->addWidget(d->mTagWidget);
}

TagWidget::~TagWidget()
{
    delete d;
}

void TagWidget::onSelectionChanged(const Akonadi::Tag::List &tags)
{
    Q_UNUSED(tags);
    d->mCachedTagNames.clear();
    const Akonadi::Tag::List tagsSelection(d->mTagWidget->selection());
    d->mCachedTagNames.reserve(tagsSelection.count());
    for (const Akonadi::Tag &tag : tagsSelection) {
        d->mCachedTagNames << tag.name();
    }
    Q_EMIT selectionChanged(d->mCachedTagNames);
    Q_EMIT selectionChanged(tags);
}

void TagWidget::setSelection(const QStringList &tagNames)
{
    d->mTagList.clear();
    d->mCachedTagNames = tagNames;
    for (const QString &name : tagNames) {
        //TODO fetch by GID instead, we don't really want to create tags here
        Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag::genericTag(name), this);
        tagCreateJob->setMergeIfExisting(true);
        connect(tagCreateJob, &Akonadi::TagCreateJob::result, this, &TagWidget::onTagCreated);
    }
}

void TagWidget::onTagCreated(KJob *job)
{
    if (job->error()) {
        qCWarning(LIBKDEPIMAKONADI_LOG) << "Failed to create tag " << job->errorString();
        return;
    }
    Akonadi::TagCreateJob *createJob = static_cast<Akonadi::TagCreateJob *>(job);
    d->mTagList << createJob->tag();
    d->mTagWidget->setSelection(d->mTagList);
}

QStringList TagWidget::selection() const
{
    return d->mCachedTagNames;
}

class KPIM::TagSelectionDialogPrivate
{
public:
    TagSelectionDialogPrivate()
    {
    }

    Akonadi::Tag::List mTagList;
};
TagSelectionDialog::TagSelectionDialog(QWidget *parent)
    : Akonadi::TagSelectionDialog(parent)
    , d(new KPIM::TagSelectionDialogPrivate)
{
}

TagSelectionDialog::~TagSelectionDialog()
{
    delete d;
}

void TagSelectionDialog::setSelection(const QStringList &tagNames)
{
    d->mTagList.clear();
    for (const QString &name : tagNames) {
        //TODO fetch by GID instead, we don't really want to create tags here
        Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag::genericTag(name), this);
        tagCreateJob->setMergeIfExisting(true);
        connect(tagCreateJob, &Akonadi::TagCreateJob::result, this, &TagSelectionDialog::onTagCreated);
    }
}

void TagSelectionDialog::onTagCreated(KJob *job)
{
    if (job->error()) {
        qCWarning(LIBKDEPIMAKONADI_LOG) << "Failed to create tag " << job->errorString();
        return;
    }
    Akonadi::TagCreateJob *createJob = static_cast<Akonadi::TagCreateJob *>(job);
    d->mTagList << createJob->tag();
    Akonadi::TagSelectionDialog::setSelection(d->mTagList);
}

QStringList TagSelectionDialog::selection() const
{
    QStringList list;
    const Akonadi::Tag::List lst = Akonadi::TagSelectionDialog::selection();
    list.reserve(lst.count());
    for (const Akonadi::Tag &tag : lst) {
        list << tag.name();
    }
    return list;
}

Akonadi::Tag::List TagSelectionDialog::tagSelection() const
{
    return Akonadi::TagSelectionDialog::selection();
}
