#include <QtGui>

#include "attributeitem.h"
#include "branchitem.h"
#include "imageitem.h"
#include "treeitem.h"
#include "treemodel.h"
#include "xlinkitem.h"

TreeModel::TreeModel(QObject *parent)
    : QAbstractItemModel(parent)
{
    //qDebug()<<"Constr TreeModel  this="<<this;
    QList<QVariant> rootData;
    rootData << "Heading" << "Type";
    rootItem = new BranchItem(rootData);
}

TreeModel::~TreeModel()
{
    //qDebug()<<"Destr TreeModel  this="<<this;
    delete rootItem;
}

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

    TreeItem *item = getItem (index);

    if (role != Qt::DisplayRole)
    {
	if (role == Qt::ForegroundRole ) 
	    return item->getHeadingColor();
	//if (role == Qt::BackgroundRole )  // does not look nice
	//  return item->getBackgroundColor();
	return QVariant();
    }	


    return item->data(index.column());
}

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

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

QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}

QModelIndex TreeModel::index (TreeItem* ti)
{
    if (!ti->parent())
	return QModelIndex();
    else    
	return createIndex (ti->row(),0,ti);
}

QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
            const
{
    // Make sure to return invalid index for invalid values (see modeltest)
    if (row<0 || column<0) return QModelIndex();
    if (column!=0) return QModelIndex();

    TreeItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = getItem (parent);

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

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

    TreeItem *ti= getItem (index);
    TreeItem *parentItem = ti->parent();
    if (parentItem == rootItem) return QModelIndex();
    return createIndex(parentItem->childNumber(), 0, parentItem);
}

int TreeModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = getItem (parent);

    return parentItem->childCount();
}

int TreeModel::columnCount(const QModelIndex &parent) const
{
    int c;
    if (parent.isValid())
        c= getItem (parent)->columnCount();
    else
        c= rootItem->columnCount();
    return c;
}

void TreeModel::nextBranch (BranchItem* &current, BranchItem* &previous, bool deepLevelsFirst, BranchItem *start)    
{
    if (deepLevelsFirst)
    {
        // Walk through map beginning at current with previous==0
        // Start at root, if current==NULL
        if (!current) 
        {
            if (start)
            {
                current=start;
                previous=current->parentBranch();
            } else
            {
                previous=(BranchItem*)rootItem;
                current = previous->getFirstBranch();
                return;
            }
        }
        
        // Walk the tree by always turning "left" 
        // and returning an element when going up
        if (current == previous)
        {
            // Had leaf before, go up again.
            if (start && start == current)
            {
                current=NULL;
                return;
            }
            current = current->parentBranch();
            if (!current) return;
            return nextBranch(current, previous, deepLevelsFirst, start);
        }

	if (current->depth() > previous->depth() )
	{   
	    // Coming from above, try to go deeper
	    if (current->branchCount() >0 )
	    {
                // Turn "left" and go deeper
		previous=current;
		current=current->getFirstBranch();
                return nextBranch (current, previous, deepLevelsFirst);
	    } else	
            {
                // turn around and go up again
                previous=current;
                return;
            }
	}   else
        {
            // Coming from below, try to go down again to siblings

            BranchItem *sibling=current->getBranchNum (previous->num()+1);
            if (sibling)
            {   
                // Found sibling of previous, go there
                previous=current;
                current=sibling;
                return nextBranch (current, previous, deepLevelsFirst, start);
            } else
            {
                // and go further up
                if (current == rootItem) current = NULL;
                previous = current;
                return;
            }
        }
    } else
    {
        // Walk through map beginning at current with previous==0
        // Start at root, if current==NULL
        if (!current) 
        {
            if (start) 
            {
                current=start;    
                previous=(BranchItem*)(start->parent() );
                return;
            } else
            {
                previous=(BranchItem*)rootItem;
                current = previous->getFirstBranch();
                return;
            }
        }


	if (current->depth() > previous->depth() )
	{   
            // Going deeper 
	    if (current->branchCount() >0 )
	    {
                // Turn "left" and go deeper
		previous=current;
		current=current->getFirstBranch();
                return;
	    } else	
            {
                // turn around and go up again
                previous=current;
                nextBranch (current, previous, deepLevelsFirst, start);
                return;
            }
        } else
        {
            if (start && previous == start)
            {
                current=NULL;
                return;
            }

            BranchItem *sibling=current->getBranchNum (previous->num()+1);
            if (sibling)
            {   
                // Found sibling of previous, go there
                previous=current;
                current=sibling;
                return; 
            } else
            {
                // no sibling, go further up left
                previous=current;
                current = current->parentBranch();
                if (!current)
                {
                    current = NULL;
                    return;
                } else
                {
                    nextBranch (current, previous, deepLevelsFirst, start);
                }
            }
            return;
        }
    }
}

bool TreeModel::removeRows ( int row, int count, const QModelIndex & parent)
{
    int last=row+count-1;
    TreeItem *pi;
    if (parent.isValid())
	pi=getItem (parent);
    else
	pi=rootItem;
    TreeItem *ti;

    for (int i=row; i<=last; i++)
    {
	ti=pi->getChildNum (row);
	pi->removeChild (row);	// does not delete object!
	delete ti;
    }
    return true;
}

TreeItem *TreeModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
	TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item) return item;
    }
    return NULL;
}

BranchItem *TreeModel::getRootItem()
{
    return rootItem;
}

int TreeModel::xlinkCount()
{
    return xlinks.count();
}

Link* TreeModel::getXLinkNum (const int &n)
{
    if (n>=0 && n<xlinks.count())
	return xlinks.at(n);
    else
	return NULL;

}

