/*
 * Copyright 2010  Jonas Emanuel Müller <zanoi@zanoi.net>
 *
 * 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, see <http://www.gnu.org/licenses/>.
 */

#include "episodeproxymodel.h"

#include <QModelIndex>
#include <QRegExp>
#include <QObject>

namespace Videocatcher {

struct EpisodeProxyModel::EpisodeProxyModelPrivate
{
    EpisodeProxyModelPrivate()
    {
    }

    ~EpisodeProxyModelPrivate()
    {
    }

    int m_channelIdFilter;
    int m_statusFilter;
    QString m_titleFilter;
    bool m_channelIdFilterEnabled;
    bool m_titleFilterEnabled;
    bool m_statusFilterEnabled;
    EpisodeModel *m_sourceEpisodeModel;
};

EpisodeProxyModel::EpisodeProxyModel(QObject* parent) : QSortFilterProxyModel(parent), d(new EpisodeProxyModelPrivate)
{
    setFilterKeyColumn(-1);
    sort(Qt::DescendingOrder);
    setDynamicSortFilter(true);
    d->m_channelIdFilterEnabled = false;
    d->m_titleFilterEnabled = false;
    d->m_statusFilterEnabled = false;
}

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

void EpisodeProxyModel::setSourceEpisodeModel(EpisodeModel* sourceEpisodeModel)
{
    setSourceModel(sourceEpisodeModel);
    d->m_sourceEpisodeModel = sourceEpisodeModel;
}

QModelIndex EpisodeProxyModel::addEpisode(const QString &title, const QString &description, const int channelId, const double datePublished, const QString &videoUrl, const double videoSize)
{
    return episodeModel()->addEpisode(title, description, channelId, datePublished, videoUrl, videoSize);
}

QModelIndex EpisodeProxyModel::findById(const int id) const
{
    return mapFromSource(episodeModel()->findById(id));
}

QModelIndex EpisodeProxyModel::findByTitle(const QString &title) const
{
    return mapFromSource(episodeModel()->findByTitle(title));
}

QModelIndex EpisodeProxyModel::findByUrl(const QString &url) const
{
    return mapFromSource(episodeModel()->findByUrl(url));
}

QModelIndexList EpisodeProxyModel::findAllbyChannelId(const int channelId) const
{
    return mapFromSourceList(episodeModel()->findAllbyChannelId(channelId));
}

QModelIndexList EpisodeProxyModel::findDownloadedEpisodes(const int channelId) const
{
    return mapFromSourceList(episodeModel()->findDownloadedEpisodes(channelId));
}

QModelIndexList EpisodeProxyModel::findDownloadingEpisodes() const
{
    return mapFromSourceList(episodeModel()->findDownloadingEpisodes());
}

QModelIndexList EpisodeProxyModel::findByVideoPath(const QRegExp &regExp) const
{
    return mapFromSourceList(episodeModel()->findByVideoPath(regExp));
}

QModelIndexList EpisodeProxyModel::findAllByTitle(const QString &title) const
{
    return mapFromSourceList(episodeModel()->findAllByTitle(title));
}

QModelIndexList EpisodeProxyModel::findAllByUrl(const QString &url) const
{
    return mapFromSourceList(episodeModel()->findAllByUrl(url));
}

int EpisodeProxyModel::id(const QModelIndex &row) const
{
    return episodeModel()->id(mapToSource(row));
}

int EpisodeProxyModel::status(const QModelIndex &row) const
{
    return episodeModel()->status(mapToSource(row));
}

QString EpisodeProxyModel::title(const QModelIndex &row) const
{
    return episodeModel()->title(mapToSource(row));
}

int EpisodeProxyModel::channelId(const QModelIndex &row) const
{
    return episodeModel()->channelId(mapToSource(row));
}

QString EpisodeProxyModel::description(const QModelIndex &row) const
{
    return episodeModel()->description(mapToSource(row));
}

double EpisodeProxyModel::videoSize(const QModelIndex &row) const
{
    return episodeModel()->videoSize(mapToSource(row));
}

QString EpisodeProxyModel::videoUrl(const QModelIndex &row) const
{
    return episodeModel()->videoUrl(mapToSource(row));
}

QString EpisodeProxyModel::videoPath(const QModelIndex &row) const
{
    return episodeModel()->videoPath(mapToSource(row));
}

double EpisodeProxyModel::datePublished(const QModelIndex &row) const
{
    return episodeModel()->datePublished(mapToSource(row));
}

bool EpisodeProxyModel::setStatus(const QModelIndex &row, const int data)
{
    return episodeModel()->setStatus(mapToSource(row), data);
}

bool EpisodeProxyModel::setTitle(const QModelIndex &row, const QString &data)
{
    return episodeModel()->setTitle(mapToSource(row), data);
}

bool EpisodeProxyModel::setDescription(const QModelIndex &row, const QString &data)
{
    return episodeModel()->setDescription(mapToSource(row), data);
}

bool EpisodeProxyModel::setChannelId(const QModelIndex &row, const int data)
{
    return episodeModel()->setChannelId(mapToSource(row), data);
}

bool EpisodeProxyModel::setVideoSize(const QModelIndex &row, const double data)
{
    return episodeModel()->setVideoSize(mapToSource(row), data);
}

bool EpisodeProxyModel::setVideoUrl(const QModelIndex &row, const QString &data)
{
    return episodeModel()->setVideoUrl(mapToSource(row), data);
}

bool EpisodeProxyModel::setVideoPath(const QModelIndex &row, const QString &data)
{
    return episodeModel()->setVideoPath(mapToSource(row), data);
}

bool EpisodeProxyModel::setDatePublished(const QModelIndex &row, const double data)
{
    return episodeModel()->setDatePublished(mapToSource(row), data);
}

bool EpisodeProxyModel::removeEpisode(const QModelIndex &index)
{
    return episodeModel()->removeEpisode(mapToSource(index));
}
    
bool EpisodeProxyModel::removeEpisodes(const QModelIndexList &indexList)
{
    return episodeModel()->removeEpisodes(mapToSourceList(indexList));
}

QModelIndex EpisodeProxyModel::findNewest(const int channelId)
{
    return mapFromSource(episodeModel()->findNewest(channelId));
}

void EpisodeProxyModel::setChannelIdFilter(const int channelId)
{
    d->m_channelIdFilter = channelId;
    setFilterRegExp(QString("%1").arg(channelId));
    invalidateFilter();
}

void EpisodeProxyModel::setTitleFilter(const QString &str)
{
    d->m_titleFilter = str;
    invalidateFilter();
}

void EpisodeProxyModel::setStatusFilter(const int status)
{
    d->m_statusFilter = status;
    invalidateFilter();
}

void EpisodeProxyModel::setChannelIdFilterEnabled(const bool enabled)
{
    d->m_channelIdFilterEnabled = enabled;
    invalidateFilter();
}

void EpisodeProxyModel::setTitleFilterEnabled(const bool enabled)
{
    d->m_titleFilterEnabled = enabled;
    invalidateFilter();
}

void EpisodeProxyModel::setStatusFilterEnabled(const bool enabled)
{
    d->m_statusFilterEnabled = enabled;
    invalidateFilter();
}

void EpisodeProxyModel::submitAll()
{
    episodeModel()->submitAll();
}

EpisodeModel* EpisodeProxyModel::episodeModel() const
{ 
    return d->m_sourceEpisodeModel;
}

QModelIndexList EpisodeProxyModel::mapFromSourceList(const QModelIndexList indexList) const
{
    QModelIndexList newIndexList;
    foreach(const QModelIndex &index, indexList)
    {
        newIndexList << mapFromSource(index);
    }
    return newIndexList;
}

QModelIndexList EpisodeProxyModel::mapToSourceList(const QModelIndexList indexList) const
{
    QModelIndexList newIndexList;
    foreach(const QModelIndex &index, indexList)
    {
        newIndexList << mapToSource(index);
    }
    return newIndexList;
}

bool EpisodeProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex channelIdIndex, titleIndex, statusIndex;
    bool acceptsChannelId, acceptsTitle, acceptsStatus;
    int channelId, status;

    if(d->m_channelIdFilterEnabled) {
        channelIdIndex = sourceModel()->index(sourceRow, Episode_Channel_Id, sourceParent);
        channelId = sourceModel()->data(channelIdIndex).toInt();
        acceptsChannelId = (channelId == d->m_channelIdFilter);
    } else {
        acceptsChannelId = true;
    }

    if(d->m_titleFilterEnabled) {
        QModelIndex titleIndex = sourceModel()->index(sourceRow, Episode_Title, sourceParent);
        acceptsTitle = sourceModel()->data(titleIndex).toString().contains(d->m_titleFilter, Qt::CaseInsensitive);
    } else {
        acceptsTitle = true;
    }
    
    if(d->m_statusFilterEnabled) {
        QModelIndex statusIndex = sourceModel()->index(sourceRow, Episode_Status, sourceParent);
        status = sourceModel()->data(statusIndex).toInt();
        acceptsStatus = (status == d->m_statusFilter);
    } else {
        acceptsStatus = true;
    }
    
    return (acceptsChannelId && acceptsTitle && acceptsStatus);
}

} //namespace Videocatcher
