/*

  Copyright (c) 2010-2019 Montel Laurent <montel@kde.org>

  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 "entitycollectionorderproxymodel.h"
#include "kernel/mailkernel.h"
#include "util/mailutil.h"
#include "mailcommon_debug.h"
#include <Collection>
#include <EntityTreeModel>
#include <Akonadi/KMime/SpecialMailCollections>
#include <AgentManager>

namespace MailCommon {
class Q_DECL_HIDDEN EntityCollectionOrderProxyModel::EntityCollectionOrderProxyModelPrivate
{
public:
    EntityCollectionOrderProxyModelPrivate()
        : manualSortingActive(false)
    {
    }

    int collectionRank(const Akonadi::Collection &collection)
    {
        const Akonadi::Collection::Id id = collection.id();
        const int cachedRank = collectionRanks.value(id, -1);
        if (cachedRank != -1) {
            return cachedRank;
        }

        int rank = 100;
        if (Kernel::folderIsInbox(collection)) {
            rank = 1;
        } else if (Kernel::self()->folderIsDraftOrOutbox(collection)) {
            if (Kernel::self()->folderIsDrafts(collection)) {
                rank = 5;
            } else {
                rank = 2;
            }
        } else if (Kernel::self()->folderIsSentMailFolder(collection)) {
            rank = 3;
        } else if (Kernel::self()->folderIsTrash(collection)) {
            rank = 4;
        } else if (Kernel::self()->folderIsTemplates(collection)) {
            rank = 6;
        } else if (MailCommon::Util::isVirtualCollection(collection)) {
            rank = 200;
        } else if (collection.parentCollection() == Akonadi::Collection::root() && MailCommon::Util::isUnifiedMailboxesAgent(collection)) {
            // special treatment for Unified Mailboxes: they are *always* on top
            rank = 0;
        } else if (!topLevelOrder.isEmpty()) {
            if (collection.parentCollection() == Akonadi::Collection::root()) {
                const QString resource = collection.resource();
                if (resource.isEmpty()) {
                    qCDebug(MAILCOMMON_LOG) << " collection has not resource: " << collection;
                    //Don't save in collectionranks because we don't have resource name => pb.
                    return rank;
                }
                const int order = topLevelOrder.indexOf(resource);
                if (order != -1) {
                    rank = order + 1; /* top-level rank "0" belongs to Unified Mailboxes */
                }
            }
        }
        collectionRanks.insert(id, rank);
        return rank;
    }

    QMap<Akonadi::Collection::Id, int> collectionRanks;
    QStringList topLevelOrder;
    bool manualSortingActive;
};

EntityCollectionOrderProxyModel::EntityCollectionOrderProxyModel(QObject *parent)
    : EntityOrderProxyModel(parent)
    , d(new EntityCollectionOrderProxyModelPrivate())
{
    setSortCaseSensitivity(Qt::CaseInsensitive);
    connect(Akonadi::SpecialMailCollections::self(), &Akonadi::SpecialMailCollections::defaultCollectionsChanged, this, &EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged);
    connect(Akonadi::SpecialMailCollections::self(), &Akonadi::SpecialMailCollections::collectionsChanged, this, &EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged);
}

EntityCollectionOrderProxyModel::~EntityCollectionOrderProxyModel()
{
    if (d->manualSortingActive) {
        saveOrder();
    }
    delete d;
}

void EntityCollectionOrderProxyModel::slotSpecialCollectionsChanged()
{
    if (!d->manualSortingActive) {
        d->collectionRanks.clear();
        invalidate();
    }
}

void EntityCollectionOrderProxyModel::setTopLevelOrder(const QStringList &list)
{
    d->topLevelOrder = list;
    clearRanks();
}

void EntityCollectionOrderProxyModel::clearRanks()
{
    d->collectionRanks.clear();
    invalidate();
}

bool EntityCollectionOrderProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
    const auto leftData = left.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
    const auto rightData = right.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
    if (!d->manualSortingActive) {
        const int rankLeft = d->collectionRank(leftData);
        const int rankRight = d->collectionRank(rightData);

        if (rankLeft < rankRight) {
            return true;
        } else if (rankLeft > rankRight) {
            return false;
        }

        return QSortFilterProxyModel::lessThan(left, right);
    }

    if (MailCommon::Util::isUnifiedMailboxesAgent(leftData)) {
        return true;
    } else {
        return EntityOrderProxyModel::lessThan(left, right);
    }
}

void EntityCollectionOrderProxyModel::setManualSortingActive(bool active)
{
    if (d->manualSortingActive == active) {
        return;
    }

    d->manualSortingActive = active;
    d->collectionRanks.clear();
    invalidate();
}

bool EntityCollectionOrderProxyModel::isManualSortingActive() const
{
    return d->manualSortingActive;
}
}
