/*
 * Copyright (C) 2008 Instituto Nokia de Tecnologia. All rights reserved.
 *
 * This file is part of QEdje.
 *
 * QEdje is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * QEdje 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with QEdje.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __QEDJE_LOADER_H__
#define __QEDJE_LOADER_H__

#include "qedje.h"


class QEdje;
class QEdjeLoader;
struct QEdjePartCollection;

struct QEdjeColorClass
{
    QString name;
    QColor color;
    QColor color2;
    QColor color3;
};

struct QEdjeData
{
    QString key;
    QString value;
};

struct QEdjeStyleTag
{
    QString key;
    QString font;
    QString value;
    double fontSize;
    QString textClass;
};

struct QEdjeStyle
{
    QString name;
    QList <QEdjeStyleTag *> tags;
    //Evas_Textblock_Style *style;

    inline void addTag(QString key, QString value, QString font,
                       double fontSize, QString textClass);
};

inline void QEdjeStyle::addTag(QString key, QString value, QString font,
                               double fontSize, QString textClass)
{
    QEdjeStyleTag *tag = new QEdjeStyleTag;
    tag->key = key;
    tag->font = font;
    tag->value = value;
    tag->fontSize = fontSize;
    tag->textClass = textClass;
    tags.append(tag);
}

struct QEdjeFontDirectoryEntry
{
    QString entry;
    QString path;
};

struct QEdjeImageDirectoryEntry
{
    int id;
    QString entry;
    int sourceType;
    int sourceParam;
};

struct QEdjePartCollectionDirectoryEntry
{
    int id;
    QString entry;
};

/*!
  \class QEdjeFile
  \brief Loaded edje data file.

  This class represents in memory the edje data file that will be loaded.
 */
class QEdjeFile
{
public:
    QEdjeFile()
    {
        _references = 0;
    }

    ~QEdjeFile();

    QString path;
    int version;
    int featureVer;
    QString compiler;
    QList <QEdjeFontDirectoryEntry *> fontDir;
    QList <QEdjeImageDirectoryEntry *> imageDir;
    QHash <QString, QEdjePartCollection *> collectionHash;
    QList <QEdjePartCollectionDirectoryEntry *> collectionDir;
    QList <QEdjeData *> data;
    QList <QEdjeStyle *> styles;
    QList <QEdjeColorClass *> colorClasses;
    QHash <QString, QString> fontHash; // (key=entry, val=path)
    QHash <QString, QString> dataCache;

    //Edje_Spectrum_Directory        *spectrum_dir;

    //Evas_Hash			  *font_hash;
    //Evas_List                      *collection_cache;
    //Eet_File                       *ef;
    //unsigned int                    free_strings : 1;

private:
    friend class QEdjeLoader;
    friend QDebug operator<<(QDebug dbg, const QEdjeFile &s);

    int _references;
};

QDebug operator<<(QDebug, const QEdjeFile &);


enum QEdjeAspectPrefer {
    None,
    Vertical,
    Horizontal,
    Both
};


struct QEdjePartDescription
{
    struct
    {
        QString name;
        double value;
    } state;

    struct
    {
        int idX;
        int idY;
        QPoint offset;
        QPointF relative;
    } rel1, rel2;

    struct
    {
        QString text;
        QString textClass;
        QString style;
        QString font;
        QPointF align;
        double elipsis;
        int size;
        int idSource;
        int idTextSource;
        bool fitX;
        bool fitY;
        bool minX;
        bool minY;
        bool maxX;
        bool maxY;
    } text;

    struct
    {
        double min;
        double max;
        QEdjeAspectPrefer prefer;
    } aspect;

    struct
    {
        int top;
        int left;
        int right;
        int bottom;
        bool noFill;
    } border;

    struct
    {
        QPoint abs;
        QPointF rel;
        QPoint posAbs;
        QPointF posRel;
        int angle;
        int spread;
        bool smooth;
        // unsigned char  type;
    } fill;

    struct
    {
        int id;
        QString type;
        QString params;
        bool useRel;

        struct {
            QPoint offset;
            QPointF relative;
        } rel1;

        struct {
            QPoint offset;
            QPointF relative;
        } rel2;
    } gradient;

    QSize min;
    QSize max;
    QPoint step;
    bool visible;
    QPointF align;
    bool fixedWidth;
    bool fixedHeight;

    QColor color;
    QColor color2;
    QColor color3;
    QString colorClass;

    int imageId; // the image id to use
    QList <int> tweenList; // list of image ids
};


struct QEdjePart
{
    static const QString PATH_SEPARATOR_STRING;

    enum TypeFlag {
        RECT = 1,
        TEXT = 2,
        IMAGE = 3,
        SWALLOW = 4,
        TEXTBLOCK = 5,
        GRADIENT = 6,
        GROUP = 7
    };

    // char pointer_mode;
    // Evas_Event_Flags       ignore_flags;

    int id;
    QString name;
    TypeFlag type;
    QString source;

    int effect;
    int clipToId;

    struct
    {
        QPoint step;
        QPoint count;
        int eventsId;
        int confineId;
        bool x;
        bool y;
    } dragable;

    bool mouseEvents;
    bool repeatEvents;
    bool preciseIsInside;
    bool useAlternateFontMetrics;

    QEdjePartDescription defaultDescription;
    QList <QEdjePartDescription *> otherDescriptions;
};


struct QEdjeProgram
{
    enum ActionType {
        ACTION_STATE_SET = 1,
        ACTION_STOP = 2,
        ACTION_SIGNAL_EMIT = 3
    };

    /* program id */
    int id;

    /* name of the action */
    QString name;

    /* if signal emission name matches the glob here... */
    QString signal;

    /* if part that emitted this (name) matches this glob */
    QString source;

    /* type - set state, stop action, set drag pos etc. */
    int action;

    /* what state of alternates to apply, NULL = default */
    QString state;

    /* what other state to use - for signal emit action */
    QString state2;

    /* value of state to apply (if multiple names match) */
    double value;

    /* other value for drag actions */
    double value2;


    double inFrom;
    double inRange;

    /* how to tween - linear, sinusoidal etc. */
    int tweenMode;

    /* time to graduate between current and new state */
    double tweenTime;

    /* list of part id or action id (targets of an action) */
    QList <int> targets;

    /* list of actions id's to execute after */
    QList <int> after;
};


struct QEdjePartCollection
{
    int id;
    QString part;
    int references;
    QList <QEdjeData *> data;
    QList <QEdjePart *> parts;
    QList <QEdjeProgram *> programs;
    QSize propMin;
    QSize propMax;

    //Embryo_Program *script; // all the embryo script code for this group
};


class QEdjeLoader
{
public:
    static QEdjeFile *load(const QString &filename);
    static void unload(const QString &filename);

private:
    static QEdjeFile *loadEdjeFile(const char *filename);
};

#endif
