/*
 * cditemmodel.cpp - model for contents tree
 * Copyright (C) 2010  Ivan Romanov <drizt@land.ru>
 * 
 * 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 <QDebug>
#include <QDir>
#include "cditemmodel.h"

CDItemModel::CDItemModel(QObject *parent)
	: QAbstractItemModel(parent)
	, rootItem_(new ContentItem(""))
{
}
CDItemModel::~CDItemModel()
{
	delete rootItem_;
}

int CDItemModel::columnCount(const QModelIndex &parent) const
{
	Q_UNUSED(parent)

	// in our model always only 1 column
	return 1;
}

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

	if(role == Qt::DisplayRole) {
		ContentItem *item = static_cast<ContentItem*>(index.internalPointer());
		return item->name();
	}

	ContentItem *item = (ContentItem*)index.internalPointer();
	if(role == Qt::CheckStateRole) {
		if(item->isInstalled()) {
			return 1;
		} else if(item->toInstall()) {
			return 2;
		} else	{
			return 0;
		}
	}
	
	return QVariant();
}

bool CDItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if(!index.isValid()) {
		return false;
	}
	
	if(role == Qt::CheckStateRole) {
		ContentItem *item = (ContentItem*)index.internalPointer();
		item->setToInstall(value.toBool());

		// set the same for the descends 
		int i = 0;
		while(index.child(i, 0).isValid()) {
			setData(index.child(i++, 0), value, role);
		}
		
		if(index.parent().isValid()) {
			if(value.toBool() == false) {
				((ContentItem*)(index.parent().internalPointer()))->setToInstall(false);
			} else {
				int i = 0;
				bool b = true;
				while(index.sibling(i, 0).isValid()) {
					b = data(index.sibling(i++, 0), role).toBool();
					if(!b) {
						break;
					}
				}
				
				((ContentItem*)(index.parent().internalPointer()))->setToInstall(b);
			}
		}

		emit dataChanged(index, index);
		emit dataChanged(index.parent(), index.parent());
		return true;
	}
	return false;
}


Qt::ItemFlags CDItemModel::flags(const QModelIndex &index) const
{
	if (!index.isValid()) {
		return 0;
	}

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

QVariant CDItemModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	Q_UNUSED(section)
	Q_UNUSED(orientation)
	Q_UNUSED(role)

	return QVariant();
}

QModelIndex CDItemModel::index(int row, int column, const QModelIndex &parent) const
{
	if (!hasIndex(row, column, parent)) {
		return QModelIndex();
	}

	ContentItem *parentItem;

	if (!parent.isValid()) {
		parentItem = rootItem_;
	} else {
		parentItem = static_cast<ContentItem*>(parent.internalPointer());
	}

	ContentItem *childItem = parentItem->child(row);
	if (childItem) {
		return createIndex(row, column, childItem);
	} else {
		return QModelIndex();
	}
}

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

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

	if (parentItem == rootItem_) {
		return QModelIndex();
	}

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

int CDItemModel::rowCount(const QModelIndex &parent) const
{
	ContentItem *parentItem;
	if (parent.column() > 0) {
		return 0;
	}

	if (!parent.isValid()) {
		parentItem = rootItem_;
	} else {
		parentItem = static_cast<ContentItem*>(parent.internalPointer());
	}
	
	return parentItem->childCount();
}

void CDItemModel::addRecord(QString group, QString name, QString url, QString html)
{
	ContentItem *parent = rootItem_;
	QStringList subGroups = group.split("/");
	
	while(!subGroups.isEmpty()) {
		ContentItem *newParent = NULL;
		for(int i = parent->childCount() - 1; i >= 0; i--) {
			if(parent->child(i)->name() == subGroups.first()) {
				newParent = parent->child(i);
				break;
			}
		}
		
		if(newParent == NULL) {
			newParent = new ContentItem(subGroups.first(), parent);
			parent->appendChild(newParent);
		}
		
		parent = newParent;
		subGroups.removeFirst();
	}
	
	ContentItem *item = new ContentItem(name, parent);
	item->setGroup(group);
	item->setUrl(url);
	item->setHtml(html);
	parent->appendChild(item);
}

QList<ContentItem*> CDItemModel::getToInstall() const
{
	QList<ContentItem*> listItems;
	QModelIndex index = this->index(0, 0);
	while(index.isValid()) {
		if(index.child(0, 0).isValid()) {
			// Descent
			index = index.child(0, 0);
		} else {
			while(index.isValid()) {
				ContentItem *item = (ContentItem*)index.internalPointer();

				if(item->toInstall()) {
					listItems << item;
				}
				
				if(!index.sibling(index.row() + 1, 0).isValid()) {
					index = index.parent();
					break;
				}
				index = index.sibling(index.row() + 1, 0);
			}
  
			while(index.parent().isValid() && !index.sibling(index.row() + 1, 0).isValid()) {
				index = index.parent();
			}

			index = index.sibling(index.row() + 1, 0);
		}
	}
	return listItems;
}

void CDItemModel::setDataDir(const QString &dataDir)
{
	dataDir_ = dataDir;
}

void CDItemModel::setResourcesDir(const QString &resourcesDir)
{
	resourcesDir_ = resourcesDir;
}

void CDItemModel::update()
{
	QModelIndex index = this->index(0, 0);
	while(index.isValid()) {
		if(index.child(0, 0).isValid()) {
			// Descent
			index = index.child(0, 0);
		} else {
			bool allInstalled = true;
			while(true) {
				ContentItem *item = (ContentItem*)index.internalPointer();
				QString filename = item->url().section("/", -1);
				QString fullFileNameH = QDir::toNativeSeparators(QString("%1/%2/%3").
																 arg(dataDir_).
																 arg(item->group()).
																 arg(filename));

				QString fullFileNameR = QDir::toNativeSeparators(QString("%1/%2/%3").
																 arg(resourcesDir_).
																 arg(item->group()).
																 arg(filename));

				if(QFile::exists(fullFileNameH) || QFile::exists(fullFileNameR)) {
					item->setToInstall(false);
					item->setIsInstalled(true);
					emit dataChanged(index, index);
				} else {
					allInstalled = false;
				}
				
				if(!index.sibling(index.row() + 1, 0).isValid()) {
					index = index.parent();
					if(allInstalled) {
						item->parent()->setIsInstalled(true);
						emit dataChanged(index, index);
					}

					break;
				}
				index = index.sibling(index.row() + 1, 0);
			}
  
			while(index.parent().isValid() && !index.sibling(index.row() + 1, 0).isValid()) {
				index = index.parent();
			}

			index = index.sibling(index.row() + 1, 0);
		}
	} 
}
