/***************************************************************************
 *   Copyright (c) 2009  Peter Mylemans <peter.mylemans@gmail.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 "CollectionTreeModel.h"
#include <QDebug>

#include "models/Movie.h"
#include "App.h"

struct TreeItem
{
    TreeItem            *parent;
    QList<TreeItem*>     children;

    TreeItem() : parent(NULL) {}
    TreeItem(TreeItem *item) : parent(item) { parent->children.append(this); }
    virtual ~TreeItem() { qDeleteAll(children);  }

    int row() const
    {
        if (parent == NULL)
            return 0;
        else
            return parent->children.indexOf(const_cast<TreeItem*>(this));
    }

    virtual bool isCollection() { return false; }
    virtual QPixmap icon() { return QPixmap(); }
    virtual QString title() { return QString(); }
};

struct CollectionTreeItem : TreeItem
{
    Collection  *collection;

    CollectionTreeItem(TreeItem *parent) : TreeItem(parent) {}

    virtual bool isCollection() { return true; }
    virtual QPixmap icon() { return collection->icon(); }
    virtual QString title() { return collection->title(); }
};

struct MovieTreeItem : TreeItem
{
    Movie *movie;

    MovieTreeItem(TreeItem *parent) : TreeItem(parent) {}

    virtual QString title() { return QString("%1 (%2)").arg(movie->title()).arg(movie->year()); }
};

CollectionTreeModel::CollectionTreeModel(QObject *parent)
    : QAbstractItemModel(parent)
{
    m_RootItem = new TreeItem();
    /*TreeItem *lc = new TreeItem(m_RootItem);
    lc->title = "Local Collection";
    TreeItem *ti = new TreeItem(lc);
    ti->title = "Wolverine";
    ti = new TreeItem(lc);
    ti->title = "Angels and Demons";*/
}

CollectionTreeModel::~CollectionTreeModel()
{
    delete m_RootItem;
}

QVariant CollectionTreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) return QVariant();

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
    if (role == Qt::DisplayRole)
        return item->title();
    else if (role == Qt::DecorationRole)
        return item->icon();
    else if (role == MetricsLine && item->isCollection())
        return QString("%1 items").arg(item->children.size());
    else
        return QVariant();
}

Qt::ItemFlags CollectionTreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::ItemIsEnabled;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant CollectionTreeModel::headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0)
        return QString("Title");

    return QVariant();
}

QModelIndex CollectionTreeModel::index(int row, int column, const QModelIndex &parent /* = QModelIndex() */) const
{
    TreeItem *pti = m_RootItem;
    if (parent.isValid())
        pti = static_cast<TreeItem*>(parent.internalPointer());

    TreeItem *ti = pti->children.at(row);
    if (ti != NULL)
        return createIndex(row, column, ti);
    else
        return QModelIndex();
}

QModelIndex CollectionTreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem = childItem->parent;

    if (parentItem == m_RootItem || parentItem == NULL)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int CollectionTreeModel::rowCount(const QModelIndex &parent /* = QModelIndex()*/) const
{
    if (!parent.isValid())
        return m_RootItem->children.size();
    else
        return static_cast<TreeItem*>(parent.internalPointer())->children.size();
}

int CollectionTreeModel::columnCount(const QModelIndex &parent /* = QModelIndex()*/) const
{
    Q_UNUSED(parent);
    return 1;
}

void CollectionTreeModel::addCollection(Collection *collection)
{
    CollectionTreeItem* cti = new CollectionTreeItem(m_RootItem);
    cti->collection = collection;

    connect(collection, SIGNAL(movieAdded(const Movie*)), this, SLOT(addMovie(const Movie*)));
    connect(collection, SIGNAL(cleared()), this, SLOT(clearCollection()));

    beginInsertRows(QModelIndex(), cti->row(), cti->row());
    endInsertRows();
}

TreeItem* CollectionTreeModel::findCollection(Collection *collection)
{
    foreach (TreeItem *child, m_RootItem->children)
    {
        CollectionTreeItem *item = static_cast<CollectionTreeItem*>(child);
        if (item->collection == collection)
            return item;
    }

    return NULL;
}

void CollectionTreeModel::addMovie(const Movie *movie)
{
    TreeItem *collection = findCollection(static_cast<Collection*>(sender()));
    if (collection == NULL)
        return;

    MovieTreeItem *treeItem = new MovieTreeItem(collection);
    treeItem->movie = const_cast<Movie*>(movie);

    beginInsertRows(createIndex(collection->row(), 0, collection), treeItem->row(), 0);
    endInsertRows();
}

void CollectionTreeModel::clearCollection()
{
    TreeItem *collection = findCollection(static_cast<Collection*>(sender()));
    if (collection == NULL)
        return;

    qDeleteAll(collection->children);
    collection->children.clear();

    reset();
}

void CollectionTreeModel::selectIndex(const QModelIndex &index)
{
    if (!index.isValid()) {
        // TODO: collection view
    } else {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        // TODO: series etc...
        MovieTreeItem *movie = dynamic_cast<MovieTreeItem*>(item);
        if (movie != NULL)
            App::self()->mainWindow()->context()->changeContext(movie->movie);
    }
}
