/*
 * models.cpp - plugin
 * Copyright (C) 2009-2010  Evgeny Khryukin
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "models.h"
#include "optionsparser.h"

#include <QDateTime>
#include <QDir>
#include <QPixmap>


//----------------------------------------
//--BaseModel-----------------------------
//----------------------------------------
void BaseModel::reset()
{
	selected_.clear();
    beginResetModel();
    endResetModel();
}

int BaseModel::selectedCount(const QModelIndex &) const
{
	return selected_.size();
}

void BaseModel::selectAll(const QModelIndexList& list)
{
	emit layoutAboutToBeChanged();
	selected_.clear();
	selected_ = list.toSet();
	emit updateLabel(0);
	emit layoutChanged();
}

void BaseModel::unselectAll()
{
	emit layoutAboutToBeChanged();
	selected_.clear();
	emit updateLabel(0);
	emit layoutChanged();
}

bool BaseModel::isSelected(const QModelIndex &index) const
{
	return selected_.contains(index);
}

Qt::ItemFlags BaseModel::flags(const QModelIndex &index) const
{
	Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;

	if(index.column() == 0)
		flags |= Qt::ItemIsUserCheckable;

	return flags;
}

bool BaseModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
	if(!index.isValid() || role != Qt::EditRole || index.column() != 0)
		return false;

	switch(value.toInt()) {
	case(0):
		if(selected_.contains(index))
			selected_.remove(index);
		break;
	case(2):
		if(!selected_.contains(index))
			selected_ << index;
		break;
	case(3):
		if(selected_.contains(index))
			selected_.remove(index);
		else
			selected_ << index;
		break;
	}

	emit dataChanged(index, index);
	emit updateLabel(0);

	return true;
}

QVariant BaseModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if (role == Qt::DisplayRole) {
		if (orientation == Qt::Horizontal) {
			return headers.at(section);
		}
		else {
			return section+1;
		}
	} else
		return QVariant();
}

int BaseModel::columnCount(const QModelIndex & /*parent*/) const
{
	return headers.size();
}


//---------------------------------------
//------BaseFileModel--------------------
//---------------------------------------
void BaseFileModel::reset()
{
	files_.clear();
	BaseModel::reset();
}


int BaseFileModel::rowCount(const QModelIndex &/* parent*/) const
{
	return files_.size();
}

QString BaseFileModel::fileName(const QModelIndex & index) const
{
	if(!index.isValid())
		return QString();

	int i = index.row();
	if(i < 0 || i >= files_.size())
		return QString();

	QString name = files_.at(i);
	return name.split("/", QString::SkipEmptyParts).last();
}

QString BaseFileModel::filePass(const QModelIndex & index) const
{
	if(!index.isValid())
		return QString();

	int i = index.row();
	if(i < 0 || i >= files_.size())
		return QString();

	return files_.at(i);
}

int BaseFileModel::fileSize(const QModelIndex & index) const
{
	if(!index.isValid())
		return 0;

	QFile file(filePass(index));

	return file.size();
}

QString BaseFileModel::fileDate(const QModelIndex & index) const
{
	if(!index.isValid())
		return QString();

	return QFileInfo(filePass(index)).created().toString("yyyy-MM-dd");
}

void BaseFileModel::deleteSelected()
{
	emit layoutAboutToBeChanged ();

	foreach(const QModelIndex& index, selected_) {
		const QString fileName = filePass(index);
		if(fileName.isEmpty())
			continue;

		QFile file(fileName);
		if(file.open(QIODevice::ReadWrite)) {
			file.remove();
		}
	}

	setDirs(dirs_);

	emit updateLabel(0);
}

void BaseFileModel::setDirs(const QStringList& dirs)
{
	reset();
	dirs_ = dirs;
	foreach(const QString& dirName, dirs_) {
		QDir Dir(dirName);
		foreach(const QString& fileName, Dir.entryList(QDir::Files)) {
			files_.append(Dir.absoluteFilePath(fileName));
		}
	}

	emit layoutChanged();
}


//----------------------------------------
//--ClearingModel-------------------------
//----------------------------------------
ClearingModel::ClearingModel(const QString& dir, QObject* parent)
	: BaseFileModel(parent)
{
	headers << tr("")
			<< tr("Nick")
			<< tr("Domain")
			<< tr("Size")
			<< tr("Creation Date");

	setDirs(QStringList() << dir);
}

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

	int i = index.column();
	QString filename = fileName(index);
	filename = filename.replace("%5f", "_");
	filename = filename.replace("%2d", "-");
	filename = filename.replace("%25", "@");
	switch(i) {
	case(0):
                if (role == Qt::CheckStateRole) {
			return isSelected(index) ? 2:0;
                } else if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
                        return QVariant("");
             case(1):
                if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole) {
			if(filename.contains("_at_"))
				return QVariant(filename.split("_at_").first());
			else
				return QVariant();
                }
             case(2):
                if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
			return QVariant(filename.split("_at_").last());
             case(3):
		if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
			return QVariant(fileSize(index));
             case(4):
		if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
			return QVariant(fileDate(index));
        }
	return QVariant();
}

//----------------------------------------
//--ClearingVcardModel--------------------
//----------------------------------------
QVariant ClearingVcardModel::data(const QModelIndex & index, int role) const
{
	if(index.column() == 2) {
		if (role == Qt::DisplayRole) {
			QString domain = fileName(index).split("_at_").last();
			domain.chop(4);
			domain = domain.replace("%5f", "_");
			domain = domain.replace("%2d", "-");
			domain = domain.replace("%25", "@");
			return QVariant(domain);
		}
	}
	return ClearingModel::data(index, role);
}


//----------------------------------------
//--ClearingHistoryModel------------------
//----------------------------------------
QVariant ClearingHistoryModel::data(const QModelIndex & index, int role) const
{
	QString filename = fileName(index);
	filename = filename.replace("%5f", "_");
	filename = filename.replace("%2d", "-");
	filename = filename.replace("%25", "@");
	if (role == Qt::DisplayRole) {
		if(index.column() == 2) {
			QString domain;
			if(filename.contains("_in_")){
				domain = filename.split("_in_").last();
				domain = domain.replace("_at_", "@");
			}
			else {
				domain = filename.split("_at_").last();
				domain.remove(".history");
			}
			return QVariant(domain);
		}
		else if(index.column() == 1) {
			QString jid;
			if(filename.contains("_in_")){
				jid = filename.split("_in_").first();
				jid = jid.replace("_at_", "@");
			}
			else {
				if(filename.contains("_at_"))
					return QVariant(filename.split("_at_").first());
				else
					return QVariant();
			}
		}
	}

	return ClearingModel::data(index, role);
}



//----------------------------------------
//--ClearingAvatarModel-------------------
//----------------------------------------
ClearingAvatarModel::ClearingAvatarModel(const QStringList& dir, QObject* parent)
	: BaseFileModel(parent)
{
	headers << tr("")
			<< tr("Avatar")
			<< tr("Size")
			<< tr("Creation Date");

	setDirs(dir);
}

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

	int i = index.column();
	QString filename = filePass(index);
	switch(i) {
	case(0):
                if (role == Qt::CheckStateRole) {
			return isSelected(index) ? 2:0;
                } else if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
                        return QVariant("");
             case(1):
                if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole) {
			QPixmap pix = QPixmap(filename);
			if(pix.isNull())
				return QVariant();
			return QVariant(pix);
                }
             case(2):
		if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
			return QVariant(fileSize(index));
             case(3):
		if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
			return QVariant(fileDate(index));
        }
	return QVariant();
}

//----------------------------------------
//--ClearingOptionsModel------------------
//----------------------------------------
ClearingOptionsModel::ClearingOptionsModel(const QString& fileName, QObject* parent)
	: BaseModel(parent)
	, fileName_(fileName)
{
	headers << tr("")
			<< tr("Options")
			<< tr("Values");

	parser_ = new OptionsParser(fileName_, this);
	options = parser_->getMissingNodesString();
}

int ClearingOptionsModel::rowCount(const QModelIndex &/* parent*/) const
{
	return options.size();
}

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

	int i = index.column();
	switch(i) {
	case(0):
                if (role == Qt::CheckStateRole) {
			return isSelected(index) ? 2:0;
                } else if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignRight | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole)
                        return QVariant("");
             case(1):
                if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignLeft | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole) {
                        return QVariant(options.at(index.row()));
                }
             case(2):
                if (role == Qt::TextAlignmentRole) {
                        return (int)(Qt::AlignLeft | Qt::AlignVCenter);
                } else if (role == Qt::DisplayRole) {
                        QDomNode node = parser_->nodeByString(options.at(index.row()));
                        return QVariant(node.toElement().text());
                }
        }
	return QVariant();
}

void ClearingOptionsModel::deleteSelected()
{
	emit layoutAboutToBeChanged ();

	setFile(fileName_);

	emit updateLabel(0);
}

void ClearingOptionsModel::reset()
{
	options.clear();
	BaseModel::reset();
}

void ClearingOptionsModel::setFile(const QString& fileName)
{
	emit layoutAboutToBeChanged ();

	reset();
	fileName_ = fileName;
	delete parser_;
	parser_ = new OptionsParser(fileName_, this);
	options = parser_->getMissingNodesString();

	emit layoutChanged();
}




//----------------------------------------
//--ClearingProxyModel--------------------
//----------------------------------------
ClearingProxyModel::ClearingProxyModel(QObject *parent)
	: QSortFilterProxyModel(parent)
{
	setDynamicSortFilter(true);
}

bool ClearingProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &parent) const
{
	QModelIndex index1 = sourceModel()->index(sourceRow, 1, parent);
	QModelIndex index2 = sourceModel()->index(sourceRow, 2, parent);
	bool b = index1.data(Qt::DisplayRole).toString().contains(filterRegExp());
	bool c = index2.data(Qt::DisplayRole).toString().contains(filterRegExp());
	return (b | c);
}
