#ifndef OBJECTS_H
#define OBJECTS_H


#include <QtCore>
#include <QtGui>
#include <QSizePolicy>
#include <QListWidget>
#include <QComboBox>
#include <QLabel>
#include <QSpinBox>


class EnumEditor : public QWidget
{
    Q_OBJECT
public slots:
    void ListSelectionChanged();
    void ComboSelectionChanged();
public:
    EnumEditor(QMetaEnum metaEnum);
private:
    QListWidget* lw;
    QComboBox* cb;
    QSpinBox* sb;
    QLabel* str;
    QMetaEnum m_metaEnum;
};


// Property Manager Supported types:
//   int, bool, double, enums, flags
//   QString, QDate, QTime, QDateTime, QKeySequence
//   QChar, QLocale, QPoint, QPointF, QSize, QSizeF
//   QRect, QRectF, QSizePolicy, QFont, QColor, QCursor


#define PROP_WRAP(type, name) \
    Q_PROPERTY(type name READ get##name WRITE set##name) \
    type get##name() const { return m_##name; } \
    void set##name(type val) { m_##name = val; } \
    type m_##name;

#define CHILD_PTR_PROP_WRAP(type, name) \
    Q_PROPERTY(type* name READ get##name WRITE set##name) \
    type* get##name() const { return m_##name; } \
    void set##name(type* val) { \
        /* if (m_##name) children().removeAll((QObject*)m_##name); */ \
        val->setParent(this); \
        m_##name = val; \
    } \
    type* m_##name = nullptr;


class MyObjectTest : public QObject
{
    Q_OBJECT
    Q_ENUMS(AnotherEnum)
    Q_ENUMS(TestEnum)
    Q_FLAGS(TestFlags)
public:
    enum TestFlags { FlagValue1 = 1, AnotherFlagValue = 2, FlagEtc = 4, FlagBlah = 8 };
    enum TestEnum { EnumValue1, AnotherValue, Etc, Blah };
    enum AnotherEnum { AEnumValue1, AnAnotherValue, Etc2 };

    explicit MyObjectTest() : QObject() {
        m_An_Int_Value = 10;
        m_A_Double = 11.0;
        //m_An_Enum = EnumValue1;
        //memset(this, 0, sizeof(MyObjectTest));
    }
    ~MyObjectTest() {
    }

    PROP_WRAP(int,     An_Int_Value)
    PROP_WRAP(bool,    A_Bool)
    PROP_WRAP(double,  A_Double)
    PROP_WRAP(TestEnum,An_Enum1)
    PROP_WRAP(TestEnum,An_Enum2)
    PROP_WRAP(QFlags<TestFlags>,A_Flags)
    PROP_WRAP(QString, A_String)
    PROP_WRAP(QDate,   A_Date)
    PROP_WRAP(QTime,   A_Time)
    PROP_WRAP(QDateTime, A_Date_and_Time)
    PROP_WRAP(QKeySequence, A_Key_Sequence)
    PROP_WRAP(QChar,   A_Char)
    PROP_WRAP(QLocale, A_Locale)
    PROP_WRAP(QPoint,  A_Point)
    PROP_WRAP(QPointF, A_PointF)
    PROP_WRAP(QSize,   A_Size)
    PROP_WRAP(QSizeF,  A_SizeF)
    PROP_WRAP(QRect,   A_Rect)
    PROP_WRAP(QRectF,  A_RectF)
    //PROP_WRAP(QSizePolicy, A_SizePolicy)
    //PROP_WRAP(QFont,   A_Font)
    PROP_WRAP(QColor,  A_Color)
    //PROP_WRAP(QCursor, A_Cursor)
    // flags
};



class Template : public QObject
{
    Q_OBJECT
public:
    PROP_WRAP(QString, Filename)
    PROP_WRAP(QColor, Color)
};


class Output : public QObject
{
    Q_OBJECT
    Q_ENUMS(FileTypes)
public:
    enum FileTypes { HTML, PDF, Markdown };
    PROP_WRAP(QString, Title)
    PROP_WRAP(QString, Filename)
    PROP_WRAP(FileTypes, FileType)
};


class Input : public QObject
{
    Q_OBJECT
public:
    PROP_WRAP(QString, Filename)
};


class Project : public QObject
{
    Q_OBJECT
    Q_ENUMS(FileTypes)
public:
    enum FileTypes { HTML, PDF, Markdown };
    //PROP_WRAP(QString, Name)
    PROP_WRAP(QString, Author)
    //PROP_WRAP(Template*, Template)
    //PROP_WRAP(QList<Input*>, Inputs)
    //PROP_WRAP(Output*, Output)

    //CHILD_PTR_PROP_WRAP(Output, Output)
    //CHILD_PTR_PROP_WRAP(Template, Template)

    PROP_WRAP(QString, Title)
    PROP_WRAP(QString, OutputFilename)
    PROP_WRAP(FileTypes, OutputFileType)

    PROP_WRAP(QString, Template)
    PROP_WRAP(QColor, Color)

    void AddInput(Input* in) { in->setParent(this); }
};


class Solution : public QObject
{
    Q_OBJECT
public:
    //PROP_WRAP(QList<Project*>, Projects)
    void AddProject(Project* proj) { proj->setParent(this); }
};


#endif // OBJECTS_H
