#ifndef PACKET_H
#define PACKET_H

#include <QString>
#include <QPolygon>
#include "frametree.h"

#ifndef Global
#define Global extern
#endif
Global int numObjects;

/*
 * Ein Objekt, welches in der Bildsequenz auf beliebig vielen Bildern auftreten kann
 */
class Object
{
private:
    QString id; // Die Objekt ID
    int classId; // Die ID der Objekt Klasse

public:
    Object( QString id, int classId );
    // Setzt die Objekt-ID
    void setId( QString id );
    // Gibt die Objekt-ID zurück
    QString getId() const;
    // Setzt die ID der Klasse
    int getClassId() const;
    // Gibt die ID der Klasse zurück
    void setClassId( int id );
};

// Vergleicht zwei Objekte anhand ihrer ID
bool operator == (const Object &p1, const Object &p2);

/*
 * Vorkommen eines Objektes auf einem Bild
 */
class _ObjectPolygon : public FrameTreeNode
{
private:
    QString id; // Die Id des Objektes
    bool truncated; // 1, falls das Objekt abgeschnitten ist
    QList< QPolygon > polygon; // Eine Liste mit Polygonen des Objektes
    bool selected; // 1, falls das Objekt nicht versteckt ist
    int ref; // Reference Counter

    _ObjectPolygon( QString id, QPolygon po, bool truncated, int index, FrameTreeNode *parent );

public:
    // Setzt die Objekt-ID
    void setId( QString id );
    // Legt fest, ob das Objekt versteckt ist (falls s = 0)
    void setSelected( bool s );
    // Entfernt alle Ecken in einer Region r. Gibt 0 zurück, fall das Objekt komplett entfernt werden soll
    bool removeVertices( QRect r );
    // Verschiebt den intex-ten Vertex aus dem pIndex-ten Polygon auf Position newPos.
    //  max: Die maximale Größe des Bildes. Falls newPos außerhalb des Bildes liegt, wird automatisch der nächste Punkt im Bild genommen.
    void moveVertex( int index, QPoint newPos, QSize max, int pIndex );
    // Fügt an Slette index im pIndexten Polygon den Eckpunkt v ein
    void insertVertex( int index, QPoint v, int pIndex );
    // Spaltet das pIndexte Polygon indem zwischen dem begin-ten Eckpunkt und dem end-ten Eckpunkt geschnitten wird.
    //  Gibt das neu entstandene Polygon zurück (eine hälfte des alten, die aus diesem entfernt wurde)
    QPolygon split( int begin, int end, int pIndex );
    // Setzt den Truncated Flag
    void setTruncated( bool truncated );
    // Gibt 1 zurück, wenn das Objekt nicht Versteckt ist
    bool isSelected() const;
    // Gibt die Bounding Box zurück
    QRect getBoundingBox() const;
    // Gibt this zurück
    void *getNodeObject() const override;
    // Gibt 1 zurück, falls Truncated gesetzt wurde
    bool isTruncated() const;
    // Gibt die Objekt-ID zurück
    QString getId() const;
    // Gibt eine Liste mit den Polygonen zurück
    QList< QPolygon > &getPolygonList();

    friend class ObjectPolygon;
};

// Ein intelegenter Zeiger auf ein _ObjektPolygon Objekt, der reference Counting verwendet
class ObjectPolygon
{
private:
    _ObjectPolygon *ptr; // Ein Zeiger auf das verwaltete Objekt

public:
    // Erstellt ein auf Null zeigendes ObjektPolygon
    ObjectPolygon();
    // Erzeugt ein neues Objekt Polygon, welches auf ein bestimmtes Objekt zeigt
    ObjectPolygon( _ObjectPolygon *ptr );
    // Erzeugt ein neues Objekt Polygon mit neuem Objekt
    //  id: Die Objekt ID
    //  po: Das Polygon
    //  truncated: 1, falls das Objekt abgeschnitten ist
    //  parent: Der Elternknoten im Baum der Sequenz (das Bild zu dem das Objekt gehört)
    ObjectPolygon( QString id, QPolygon po, bool truncated, int index, FrameTreeNode *parent );
    // Copy Constructor
    ObjectPolygon( const ObjectPolygon &op );
    ~ObjectPolygon();

    // Operator um auf das unterliegende _ObjectPolygon zuzugreifen
    _ObjectPolygon *operator->() const;
    // Gibt 1 zurück, falls auf das gleiche Objekt verwiesen wird
    bool operator==( const ObjectPolygon &op ) const;
    // Gibt 1 zurück, falls nicht auf das gleiche Objekt verwiesen wird
    bool operator!=( const ObjectPolygon &op ) const;
    // Setzt den Zeiger auf das _ObjectPolygon Objekt
    bool operator=( const ObjectPolygon &op );
    // Gibt 1 zurück, falls der Zeiger nicht inizialisiert wurde
    bool isNull() const;
};

#endif // PACKET_H
