/**************************************************************************
** Piperka Client
** Copyright (C) 2019  Kari Pahula
**
** 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 "comic.h"
#include "sortmanager.h"
#include "updates.h"

UpdatesModel::UpdatesModel(const SortManager &mgr, QObject *parent)
    : QSortFilterProxyModel(parent)
    , m_mgr(mgr)
    , subscriptionTimeout(this)
{
    sort(0);
    /* For some reason, initial data load without timer use leads to off by
     *  one error with comics in updatesModel.
     */
    subscriptionTimeout.setSingleShot(true);
    connect(&subscriptionTimeout, &QTimer::timeout, this,
           [=]() {
        if (!m_subscriptionFlag)
            return;
        invalidateFilter();
        invalidate();
        int oldUnreadCount = m_unreadCount;
        m_unreadCount = countUnreadPages();
        if (oldUnreadCount != m_unreadCount)
            emit unreadPagesChanged();
        bool oldNoUnread = m_noUnread;
        m_noUnread = rowCount() == 0;
        if (oldNoUnread != m_noUnread)
            emit noUnreadChanged();
        m_subscriptionFlag = false;
        emit subscriptionFlagChange();
    });
}

void UpdatesModel::setSource(QAbstractItemModel *model)
{
    connect(model, &QAbstractItemModel::rowsInserted,
            this, &UpdatesModel::subscriptionChange);
    setSourceModel(model);
}

void UpdatesModel::setSortType(const int &sortType)
{
    // 1 is switched to 3 to share most recently updated with BrowseModel
    if (sortType == m_sortType)
        return;
    else if (sortType == 1) {
        emit sortTypeChangePrepare(3);
        return;
    } else {
        m_sortType = sortType;
    }
    emit sortTypeChanged();
    sort(0);
    subscriptionChange();
}

int UpdatesModel::firstCid() const
{
    QVariant cid = data(index(0,0), ComicModel::CidRole);
    return cid.isValid() ? cid.toInt() : -1;
}

int UpdatesModel::countUnreadPages() const
{
    int total = 0;
    for (int i = 0; i < rowCount(); ++i) {
        QVariant rowData = data(index(i, 0), ComicModel::UnreadCountRole);
        if (rowData.isValid()) {
            int count = rowData.toInt();
            if (count > 0)
                total += count;
        }
    }
    return total;
}

void UpdatesModel::sortDownloaded(const int &sortType, const QJsonDocument &doc)
{
    Q_UNUSED(doc);
    // Only use last updated sort from downloaded sort types
    if (sortType != 3)
        return;
    m_sortType = 1;
    emit sortTypeChanged();
    subscriptionChange();
}

void UpdatesModel::subscriptionChange()
{
    m_subscriptionFlag = true;
    emit subscriptionFlagChange();
    subscriptionTimeout.start(1);
}

void UpdatesModel::loggedOut()
{
    if (m_unreadCount > 0) {
        m_unreadCount = 0;
        emit unreadPagesChanged();
    }
    if (!m_noUnread) {
        m_noUnread = true;
        emit noUnreadChanged();
    }
    m_subscriptionFlag = false;
}

bool UpdatesModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
    QVariant unread = sourceModel()->data(index, ComicModel::UnreadCountRole);
    return unread.isValid() && unread > 0;
}

bool UpdatesModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
    if (m_sortType == 0) {
        // Least new pages first
        int num1 = sourceModel()->data(source_left, ComicModel::UnreadCountRole).toInt();
        int num2 = sourceModel()->data(source_right, ComicModel::UnreadCountRole).toInt();
        if (num1 != num2)
            return num1 < num2;
    } else if (m_sortType == 1) {
        // Most recently updated
        int cid1 = sourceModel()->data(source_left, ComicModel::CidRole).toInt();
        int cid2 = sourceModel()->data(source_right, ComicModel::CidRole).toInt();
        int prio1 = m_mgr.sortUpdated().value(cid1);
        int prio2 = m_mgr.sortUpdated().value(cid2);
        if (prio1 != prio2)
            return prio1 > prio2;
    }
    // m_sortType == 2 Alphabetical and fall through
    return sourceModel()->data(source_left, ComicModel::NativeOrderRole).toInt() <
            sourceModel()->data(source_right, ComicModel::NativeOrderRole).toInt();
}
