#include "frametreemodel.h"
#include <QDebug>
#include "object.h"
#include <QIcon>

FrameTreeModel::FrameTreeModel()
    : QAbstractItemModel(),
      seq( 0 )
{

}

FrameTreeModel::~FrameTreeModel()
{
    if( seq )
        seq->refRelease();
}

// Prüft, ob ein Index valide ist
bool FrameTreeModel::isIndexValid( const QModelIndex &i ) const
{
    return i.internalPointer() != 0 && ((FrameTreeNode*)i.internalPointer())->getDepth() <= 2 &&
            ((FrameTreeNode*)i.internalPointer())->getDepth() >= 0 &&
            ((FrameTreeNode*)i.internalPointer())->getIndex() >= 0;
}

// Setzt die Sequenz, welche momenatan annotiert wird
//  s: die neue Sequenz
void FrameTreeModel::setSequenz( Sequenz *s )
{
    if( seq )
        seq->refRelease();
    seq = s;
    this->dataChanged( createIndex( 0, 0 ), createIndex( 1, 1 ) );
}

// Gibt zurück, was für einen bestimten Knoten angezeigt werden soll
//  index: Der Index des Knotens
//  role: Welche daten des Knotens abgefragt werden sollen (z.B.:Name oder Hintergrundfarbe...)
QVariant FrameTreeModel::data(const QModelIndex &index, int role) const
{
    switch( role )
    {
    case Qt::DisplayRole:
        if (!index.isValid() || role != Qt::DisplayRole || seq == 0 )
            return QVariant();
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 0 && index.column() == 0 )
            return QVariant( ((Kamera*)((FrameTreeNode*)index.internalPointer()))->getName() );
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 1 )
            return QVariant( ((Frame*)index.internalPointer())->getName() );
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 2 && index.column() == 0 )
        {
            QString objectId = ((_ObjectPolygon*)((FrameTreeNode*)index.internalPointer()))->getId();
            return QVariant( objectId + " " + seq->getClassName( seq->getClassOfObject( objectId ) ) );
        }
    case Qt::DecorationRole:
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 1 )
        {
            if( !((Frame*)index.internalPointer())->isCorrectAnnotated() )
                return QIcon(":/icons/warning.png");
        }
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 0 )
        {
            if( !((Kamera*)index.internalPointer())->isCorrectAnnotated() )
                return QIcon(":/icons/warning.png");
        }
        break;
    case Qt::BackgroundRole:
        if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 1 )
        {
            if( ((Frame*)index.internalPointer())->isNotAnnotated() )
                return QColor( 0x50, 0x50, 0x50 );
            if( seq && ((Frame*)index.internalPointer())->getIndex() == seq->getSelectedFrame() )
                return QColor( 48, 140, 198 );
        }
    }
    return QVariant();
}

// Gibt die Flags eines Knotens zurück
//  index: Der Index des Knotens
Qt::ItemFlags FrameTreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid() || seq == 0)
        return 0;
    return QAbstractItemModel::flags(index);
}

// Gibt die Grunddaten zurück, welche für das zeichnen benötigt werden
QVariant FrameTreeModel::headerData(int section, Qt::Orientation orientation,
                    int role) const
{
    if( orientation == Qt::Horizontal && role == Qt::DisplayRole )
        return QVariant( "Kameras" );
    return QVariant();
}
QModelIndex FrameTreeModel::index(int row, int column,
                  const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent) || seq == 0)
        return QModelIndex();

    if( !parent.isValid() )
    {
        return createIndex( row, column, seq->getCameras().at( row ) );
    }
    else
    {
        if( ((FrameTreeNode*)parent.internalPointer())->getDepth() == 0 )
            return createIndex( row, column, ((Kamera*)((FrameTreeNode*)parent.internalPointer()))->getFrame( row )->getNodeObject() );
        if( ((FrameTreeNode*)parent.internalPointer())->getDepth() == 1 )
            return createIndex( row, column, ((Frame*)((FrameTreeNode*)parent.internalPointer()))->getObjects().at( row )->getNodeObject() );
    }
    return QModelIndex();
}

// gibt den Index des Elternknotens zurück
QModelIndex FrameTreeModel::parent(const QModelIndex &index) const
{
    FrameTreeNode *node = (FrameTreeNode*)index.internalPointer();
    if (!index.isValid() || seq == 0 || node == 0 || node->getParent() == 0 || !isIndexValid( index ) )
        return QModelIndex();
    return createIndex( node->getParent()->getIndex(), 0, node->getParent()->getNodeObject() );
}

// gibt die Anzahl der Kindknoten zurück
int FrameTreeModel::rowCount(const QModelIndex &parent) const
{
    if( seq == 0 )
        return 0;
    if( !parent.isValid() || parent.internalPointer() == 0 || !isIndexValid( parent ))
        return seq->getCameras().count();
    else
        return ((FrameTreeNode*)parent.internalPointer())->getChildCount();
}

// gibt die Anzahl der Attribute eines Kindknotens zurück
int FrameTreeModel::columnCount(const QModelIndex &parent) const
{
    if( seq == 0 )
        return 0;
    return 1;
}

// Ermittelt die zugehörige Kamera und das Zugehörige Bild eines Knotens
bool FrameTreeModel::clickedOnFrame( const QModelIndex &index, int &camera, int &frame ) const
{
    if( ((FrameTreeNode*)index.internalPointer())->getDepth() == 1 )
    {
        frame = ((FrameTreeNode*)index.internalPointer())->getIndex();
        camera = ((FrameTreeNode*)index.internalPointer())->getParent()->getIndex();
        return true;
    }
    return false;
}

// Gibt den Index des ausgewählten Bildes zurück
QModelIndex FrameTreeModel::getFrameSelectionIndex() const
{
    Frame *selection = seq->getFrame();
    return createIndex( selection->getIndex(), 0, selection );
}

// Gibt den Index der ausgewählten Kamera zurück
QModelIndex FrameTreeModel::getCameraSelectionIndex() const
{
    return createIndex( seq->getSelectedCamera(), 0, (void*) &seq->getCameras().at( seq->getSelectedCamera() ) );
}

// Gibt eine Liste mit ausgewählten Objekten zurück
QList<QModelIndex> FrameTreeModel::getSelectedPackages() const
{
    QList<QModelIndex> list;
    Frame *selectedFrame = seq->getFrame();
    QList<ObjectPolygon> objects = selectedFrame->getObjects();
    for( int i = 0; i < objects.size(); i++ )
    {
        if( objects.at( i )->isSelected() )
            list.append( createIndex( i, 0, objects.at( i )->getNodeObject() ) );
    }
    return list;
}

// Aktualisiert die Tree View
void FrameTreeModel::update()
{
    this->dataChanged( createIndex( 0, 0, seq->getCameras().at( 0 ) ), createIndex( seq->getCameras().size() - 1, 0, seq->getCameras().last() ) );
}
