/*
 * 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 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with QEdje.  If not, see <http://www.gnu.org/licenses/>.
 *
 * This file incorporates work covered by the license described in the
 * file COPYING.libedje.
 */

#include "qedjeloader.h"

#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#include <Eet.h>

// edje program action constant
#define SIGNAL_EMIT 3

EAPI Eet_Data_Descriptor *descriptorEdjeFile = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeStyle = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeStyleTag = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeColorClass = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeData = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeFontDirectory = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeFontDirectoryEntry = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeImageDirectory = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeImageDirectoryEntry = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeSpectrumDirectory = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeSpectrumDirectoryEntry = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeSpectrumColor = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeProgram = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeProgramTarget = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjeProgramAfter = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePartCollectionDirectory = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePartCollectionDirectoryEntry = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePartCollection = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePart = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePartDescription = NULL;
EAPI Eet_Data_Descriptor *descriptorEdjePartImageId = NULL;


/*!
  This loader extracts edj information creating a data descriptor for every
  edje structs (old code dependency). This is the eet way. The problem is
  that we need to replicate original edje structs to do this. This will need
  a future code refactory. The best way to do this is to create a walker in eet,
  so we won't need this old structs anymore.
*/

typedef enum Edje_Part_Event_Flags
{
   EDJE_PART_EVENT_FLAG_NONE = 0, /* No fancy flags set */
   EDJE_PART_EVAS_EVENT_FLAG_ON_HOLD = (1 << 0)
   /* This event is being delivered but should be put "on hold" until the on
      hold flag is unset. the event should be used for informational purposes
      and maybe some indications visually, but not actually perform anything */
} Edje_Part_Event_Flags;


typedef struct QEdjeSize
{
    int width;
    int height;
} QEdjeSize;


typedef struct QEdjePoint
{
    int x;
    int y;
} QEdjePoint;


typedef struct QEdjePointF
{
    double x;
    double y;
} QEdjePointF;


typedef struct QEdjeColor
{
    int red;
    int green;
    int blue;
    int alpha;
} QEdjeColor;


typedef struct Edje_Style
{
    char *name;
    QList <void *> *tags;
    //Evas_Textblock_Style *style;
} Edje_Style;


typedef struct Edje_Style_Tag
{
    const char *key;
    const char *value;
    const char *font;
    double fontSize;
    const char *textClass;
} Edje_Style_Tag;


typedef struct Edje_Color_Class
{
    const char    *name;
    unsigned char  r, g, b, a;
    unsigned char  r2, g2, b2, a2;
    unsigned char  r3, g3, b3, a3;
} Edje_Color_Class;


typedef struct Edje_Part_Image_Id
{
    int id;
} Edje_Part_Image_Id;


typedef struct Edje_Font_Directory
{
    QList <void *> *entries;
} Edje_Font_Directory;


typedef struct Edje_Font_Directory_Entry
{
    const char *entry; /* the name of the font */
    const char *path;
} Edje_Font_Directory_Entry;


typedef struct Edje_Image_Directory
{
    QList <void *> *entries;
} Edje_Image_Directory;


typedef struct Edje_Image_Directory_Entry
{
    char *entry; /* the nominal name of the image - if any */
    int sourceType; /* alternate source mode. 0 = none */
    int sourceParam; /* extra params on encoding */
    int id; /* the id no. of the image */
} Edje_Image_Directory_Entry;


typedef struct Edje_Spectrum_Color
{
    int r, g, b, a;
    int d;
} Edje_Spectrum_Color;


typedef struct Edje_Spectrum_Directory
{
    QList <void *> *entries; /* a list of Edje_Spectrum_Directory_Entry */
} Edje_Spectrum_Directory;


typedef struct Edje_Spectrum_Directory_Entry
{
    char *entry;
    /* only one of the following two should be included. filename takes precedence */
    char *filename; /* filename of external spectrum. */
    QList <void *> *colorList; /* list of Edje_Spectrum_Color */
    int id;
} Edje_Spectrum_Directory_Entry;


typedef struct Edje_Part_Collection_Directory
{
    QList <void *> *entries; /* a list of Edje_Part_Collection_Directory_Entry */
    int references;
} Edje_Part_Collection_Directory;


typedef struct Edje_Part_Collection_Directory_Entry
{
    const char *entry; /* the nominal name of the part collection */
    int id; /* the id of this named part collection */
} Edje_Part_Collection_Directory_Entry;


typedef struct Edje_Data
{
    char *key;
    char *value;
} Edje_Data;


typedef struct Edje_Program
{
    int id; /* id of program */
    const char *name; /* name of the action */
    const char *signal; /* if signal emission name matches the glob here... */
    const char *source; /* if part that emitted this (name) matches this glob */

    struct {
        double from;
        double range;
    } in;

    int action; /* type - set state, stop action, set drag pos etc. */
    char *state; /* what state of alternates to apply, NULL = default */
    char *state2; /* what other state to use - for signal emit action */
    double value; /* value of state to apply (if multiple names match) */
    double value2; /* other value for drag actions */

    struct {
        int mode; /* how to tween - linear, sinusoidal etc. */
        double time; /* time to graduate between current and new state */
    } tween;

    QList <void *> *targets; /* list of target parts to apply the state to */

    QList <void *> *after; /* list of actions to run at the end of this, for looping */
} Edje_Program;


typedef struct Edje_Program_Target
{
    int id; /* just the part id no, or action id no */
} Edje_Program_Target;


typedef struct Edje_Program_After
{
    int id;
} Edje_Program_After;


typedef struct Edje_Part_Collection
{
    QList <void *> *programs; /* a list of Edje_Program */
    QList <void *> *parts; /* a list of Edje_Part */
    QList <void *> *data;
    int id; /* the collection id */

    struct {
        QEdjeSize min, max;
    } prop;

    int references;

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

    const char *part;
} Edje_Part_Collection;


typedef struct Edje_File
{
    const char *path;
    Edje_Font_Directory *fontDir;
    Edje_Image_Directory *imageDir;
    Edje_Spectrum_Directory *spectrumDir;
    Edje_Part_Collection_Directory *collectionDir;
    QList <void *> *data;
    QList <void *> *styles;
    QList <void *> *colorClasses;
    int references;
    char *compiler;
    int version;
    int featureVer;
    QHash <QString, void *> *collectionHash;
    QHash <QString, void *> *fontHash;
    QList <void *> *collectionCache;
    QHash <QString, void *> *dataCache;
    Eet_File  *ef;
    unsigned int freeStrings : 1;
} Edje_File;


typedef struct Edje_Part_Description
{
    struct
    {
        const char *name; /* the named state if any */
        double value; /* the value of the state (for ranges) */
    } state;

    QEdjePointF align; /* 0 <-> 1.0 alignment within allocated space */

    struct
    {
        bool width;
        bool height;
        /* width or height is fixed in side (cannot expand with Edje object size) */
    } fixed;

    QEdjeSize min, max;
    QEdjePoint step; /* size stepping by n pixels, 0 = none */

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

    struct
    {
        int idX; /* -1 = whole part collection, or part ID */
        int idY; /* -1 = whole part collection, or part ID */
        QEdjePoint offset;
        QEdjePointF relative;
    } rel1, rel2;

    struct
    {
        int id; /* the image id to use */
        QList <void *> *tweenList; /* list of Edje_Part_Image_Id */
    } image;

    struct
    {
        char *type; /* type of spectrum - 'linear', 'radial', etc */
        char *params; /* params for spectrum type */
        int id; /* the spectrum id to use */
        int useRel; /* 1 - use rel1,rel2; 0 - use fill */
        struct {
            QEdjePoint offset;
            QEdjePointF relative;
        } rel1, rel2; /* linear gradient fill options */
    } gradient;

    struct
    {
        /* border scaling on image fill */
        int top;
        int left;
        int right;
        int bottom;
        unsigned char noFill; /* do we fill the center of the
                                 image if bordered? 1 == NO!!!! */
    } border;

    struct
    {
        QEdjePoint abs;     /* size of fill added to relative fill */
        QEdjePointF rel;    /* relative size compared to area */
        QEdjePoint posAbs;  /* fill offset added to fill offset */
        QEdjePointF posRel; /* fill offset relative to area */
        int angle; /* angle of fill -- currently only used by grads */
        int spread; /* spread of fill -- currently only used by grads */
        bool smooth; /* fill with smooth scaling or not */
        unsigned char type; /* fill coordinate from container (SCALE) or from source image (TILE) */
    } fill;

    struct
    {
        char *text; /* if "" or NULL, then leave text unchanged */
        char *textClass; /* how to apply/modify the font */
        char *style; /* the text style if a textblock */
        char *font; /* if a specific font is asked for */

        QEdjePointF align; /* text alignment within bounds */

        double elipsis; /* 0.0 - 1.0 defining where the elipsis align */
        int size; /* 0 = use user set size */
        int idSource; /* -1 if none */
        int idTextSource; /* -1 if none */

        bool fitX; /* resize font size down to fit in x dir */
        bool fitY; /* resize font size down to fit in y dir */
        bool minX; /* if text size should be part min size */
        bool minY; /* if text size should be part min size */
        bool maxX; /* if text size should be part max size */
        bool maxY; /* if text size should be part max size */
    } text;

    char *colorClass; /* how to modify the color */

    /* color for rect or text, shadow etc. */
    QEdjeColor color;
    QEdjeColor color2;
    QEdjeColor color3;

    bool visible;
} Edje_Part_Description;


typedef struct Edje_Part
{
    const char *name; /* the name if any of the part */
    Edje_Part_Description *defaultDescription; /* the part descriptor for default */
    QList <void *> *otherDescriptions; /* other possible descriptors */
    const char *source;
    int id; /* its id number */
    int clipToId; /* the part id to clip this one to */
    struct {
        QEdjePoint step; /* drag jumps n pixels (0 = no limit) */
        QEdjePoint count; /* drag area divided by n (0 = no limit) */
        int confineId; /* dragging within this bit, -1 = no */
        /* davinchi */
        int eventsId; /* If it is used as scrollbar */
        bool x; /* can u click & drag this bit in x dir */
        bool y; /* can u click & drag this bit in y dir */
    } dragable;
    unsigned char type; /* what type (image, rect, text) */
    unsigned char effect; /* 0 = plain... */
    bool mouseEvents; /* it will affect/respond to mouse events */
    bool repeatEvents; /* it will repeat events to objects below */
    Edje_Part_Event_Flags ignoreFlags;
    bool preciseIsInside;
    bool useAlternateFontMetrics;
    char pointerMode;
} Edje_Part;



#define NEWD(str, typ)                          \
    { eddc.name = str; eddc.size = sizeof(typ); }

#define FREED(eed)                              \
    if (eed) {                                  \
        eet_data_descriptor_free((eed));        \
        (eed) = NULL;                           \
    }


static char *addStringDirect(const char *str)
{
    return (char *)str;
}

static void delStringDirect(const char * /*str*/)
{

}

static void *appendListItem(void *lst, void *data)
{
    QList <void *> *l;

    if (!lst)
        l = new QList <void *>();
    else
        l = (QList <void *> *) lst;

    l->append(data);

    return (void *) l;
}

static char *addStringShare(const char *val)
{
    return (char *) val;
}

static void delStringShare(const char * /*val*/)
{

}

/*!
  \internal

  Setup Edje data descriptors for eet, to load all eet file to memory.
*/
static void setupEetDataDescriptors()
{
    Eet_Data_Descriptor_Class eddc;

    eddc.version = EET_DATA_DESCRIPTOR_CLASS_VERSION;
    eddc.func.mem_alloc = NULL;
    eddc.func.mem_free = NULL;
    eddc.func.str_alloc = addStringShare;
    eddc.func.str_free = delStringShare;
    eddc.func.list_next = NULL;
    eddc.func.list_append = appendListItem;
    eddc.func.list_data = NULL;
    eddc.func.list_free = NULL;
    eddc.func.hash_foreach = NULL;
    eddc.func.hash_add = NULL;
    eddc.func.hash_free = NULL;
    eddc.func.str_direct_alloc = addStringDirect;
    eddc.func.str_direct_free = delStringDirect;

    NEWD("Edje_Font_Directory_Entry", Edje_Font_Directory_Entry);
    descriptorEdjeFontDirectoryEntry = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeFontDirectoryEntry,
                                  Edje_Font_Directory_Entry, "entry",
                                  entry, EET_T_STRING);

    NEWD("Edje_Font_Directory", Edje_Font_Directory);
    descriptorEdjeFontDirectory = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeFontDirectory,
                                 Edje_Font_Directory, "entries",
                                 entries, descriptorEdjeFontDirectoryEntry);

    NEWD("Edje_Image_Directory_Entry", Edje_Image_Directory_Entry);
    descriptorEdjeImageDirectoryEntry = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeImageDirectoryEntry,
                                  Edje_Image_Directory_Entry, "entry",
                                  entry, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeImageDirectoryEntry,
                                  Edje_Image_Directory_Entry, "source_type",
                                  sourceType, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeImageDirectoryEntry,
                                  Edje_Image_Directory_Entry, "source_param",
                                  sourceParam, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeImageDirectoryEntry,
                                  Edje_Image_Directory_Entry, "id",
                                  id, EET_T_INT);

    NEWD("Edje_Image_Directory", Edje_Image_Directory);
    descriptorEdjeImageDirectory = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeImageDirectory,
                                 Edje_Image_Directory, "entries",
                                 entries, descriptorEdjeImageDirectoryEntry);

    NEWD("Edje_Spectrum_Color", Edje_Spectrum_Color);
    descriptorEdjeSpectrumColor = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumColor,
                                  Edje_Spectrum_Color, "r", r, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumColor,
                                  Edje_Spectrum_Color, "g", g, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumColor,
                                  Edje_Spectrum_Color, "b", b, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumColor,
                                  Edje_Spectrum_Color, "a", a, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumColor,
                                  Edje_Spectrum_Color, "d", d, EET_T_INT);

    NEWD("Edje_Spectrum_Directory_Entry", Edje_Spectrum_Directory_Entry);
    descriptorEdjeSpectrumDirectoryEntry =
        eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumDirectoryEntry,
                                  Edje_Spectrum_Directory_Entry, "entry",
                                  entry, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumDirectoryEntry,
                                  Edje_Spectrum_Directory_Entry, "filename",
                                  filename, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeSpectrumDirectoryEntry,
                                 Edje_Spectrum_Directory_Entry, "color_list",
                                 colorList, descriptorEdjeSpectrumColor);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeSpectrumDirectoryEntry,
                                  Edje_Spectrum_Directory_Entry, "id",
                                  id, EET_T_INT);

    NEWD("Edje_Spectrum_Directory", Edje_Spectrum_Directory);
    descriptorEdjeSpectrumDirectory =
        eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeSpectrumDirectory,
                                 Edje_Spectrum_Directory, "entries",
                                 entries, descriptorEdjeSpectrumDirectoryEntry);

    NEWD("Edje_Part_Collection_Directory_Entry", Edje_Part_Collection_Directory_Entry);
    descriptorEdjePartCollectionDirectoryEntry = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollectionDirectoryEntry,
                                  Edje_Part_Collection_Directory_Entry, "entry",
                                  entry, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollectionDirectoryEntry,
                                  Edje_Part_Collection_Directory_Entry, "id",
                                  id, EET_T_INT);

    NEWD("Edje_Part_Collection_Directory", Edje_Part_Collection_Directory);
    descriptorEdjePartCollectionDirectory = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePartCollectionDirectory,
                                 Edje_Part_Collection_Directory, "entries",
                                 entries, descriptorEdjePartCollectionDirectoryEntry);

    NEWD("Edje_Data", Edje_Data);
    descriptorEdjeData = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeData,
                                  Edje_Data, "key", key, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeData,
                                  Edje_Data, "value", value, EET_T_STRING);

    NEWD("Edje_Style_Tag", Edje_Style_Tag);
    descriptorEdjeStyleTag = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeStyleTag,
                                  Edje_Style_Tag, "key", key, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeStyleTag,
                                  Edje_Style_Tag, "value", value, EET_T_STRING);

    NEWD("Edje_Style", Edje_Style);
    descriptorEdjeStyle = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeStyle,
                                  Edje_Style, "name", name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeStyle,
                                 Edje_Style, "tags", tags, descriptorEdjeStyleTag);

    NEWD("Edje_Color_Class", Edje_Color_Class);
    descriptorEdjeColorClass = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "name", name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "r", r, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "g", g, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "b", b, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "a", a, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "r2", r2, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "g2", g2, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "b2", b2, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "a2", a2, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "r3", r3, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "g3", g3, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "b3", b3, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeColorClass,
                                  Edje_Color_Class, "a3", a3, EET_T_UCHAR);

    NEWD("Edje_File", Edje_File);
    descriptorEdjeFile = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeFile,
                                  Edje_File, "compiler", compiler, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeFile,
                                  Edje_File, "version", version, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeFile,
                                  Edje_File, "feature_ver", featureVer, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_SUB(descriptorEdjeFile,
                                Edje_File, "font_dir", fontDir,
                                descriptorEdjeFontDirectory);
    EET_DATA_DESCRIPTOR_ADD_SUB(descriptorEdjeFile,
                                Edje_File, "image_dir", imageDir,
                                descriptorEdjeImageDirectory);
    EET_DATA_DESCRIPTOR_ADD_SUB(descriptorEdjeFile,
                                Edje_File, "spectrum_dir", spectrumDir,
                                descriptorEdjeSpectrumDirectory);
    EET_DATA_DESCRIPTOR_ADD_SUB(descriptorEdjeFile,
                                Edje_File, "collection_dir", collectionDir,
                                descriptorEdjePartCollectionDirectory);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeFile,
                                 Edje_File, "data", data, descriptorEdjeData);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeFile,
                                 Edje_File, "styles", styles,
                                 descriptorEdjeStyle);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeFile,
                                 Edje_File, "color_classes", colorClasses,
                                 descriptorEdjeColorClass);

    NEWD("Edje_Program_Target", Edje_Program_Target);
    descriptorEdjeProgramTarget = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgramTarget,
                                 Edje_Program_Target, "id", id, EET_T_INT);

    NEWD("Edje_Program_After", Edje_Program_After);
    descriptorEdjeProgramAfter = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgramAfter,
                                 Edje_Program_After, "id", id, EET_T_INT);

    NEWD("Edje_Program", Edje_Program);
    descriptorEdjeProgram = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "id", id, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "name", name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "signal", signal, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "source", source, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "in.from", in.from, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "in.range", in.range, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "action", action, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "state", state, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "state2", state2, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "value", value, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "value2", value2, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "tween.mode", tween.mode, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjeProgram,
                                  Edje_Program, "tween.time", tween.time, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeProgram,
                                 Edje_Program, "targets", targets,
                                 descriptorEdjeProgramTarget);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjeProgram,
                                 Edje_Program, "after", after,
                                 descriptorEdjeProgramAfter);

    NEWD("Edje_Part_Image_Id", Edje_Part_Image_Id);
    descriptorEdjePartImageId = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartImageId,
                                  Edje_Part_Image_Id, "id", id, EET_T_INT);

    NEWD("Edje_Part_Description", Edje_Part_Description);
    descriptorEdjePartDescription = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "state.name",
                                  state.name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "state.value",
                                  state.value, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "visible",
                                  visible, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "align.x",
                                  align.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "align.y",
                                  align.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fixed.w",
                                  fixed.width, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fixed.h",
                                  fixed.height, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "min.w",
                                  min.width, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "min.h",
                                  min.height, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "max.w",
                                  max.width, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "max.h",
                                  max.height, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "step.x",
                                  step.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "step.y",
                                  step.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "aspect.min",
                                  aspect.min, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "aspect.max",
                                  aspect.max, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "aspect.prefer",
                                  aspect.prefer, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.relative_x",
                                  rel1.relative.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.relative_y",
                                  rel1.relative.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.offset_x",
                                  rel1.offset.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.offset_y",
                                  rel1.offset.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.id_x",
                                  rel1.idX, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel1.id_y",
                                  rel1.idY, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.relative_x",
                                  rel2.relative.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.relative_y",
                                  rel2.relative.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.offset_x",
                                  rel2.offset.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.offset_y",
                                  rel2.offset.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.id_x",
                                  rel2.idX, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "rel2.id_y",
                                  rel2.idY, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "image.id",
                                  image.id, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePartDescription,
                                 Edje_Part_Description, "image.tween_list",
                                 image.tweenList, descriptorEdjePartImageId);

    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "border.l",
                                  border.left, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "border.r",
                                  border.right, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "border.t",
                                  border.top, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "border.b",
                                  border.bottom, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "border.no_fill",
                                  border.noFill, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.smooth",
                                  fill.smooth, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.pos_rel_x",
                                  fill.posRel.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.pos_abs_x",
                                  fill.posAbs.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.rel_x",
                                  fill.rel.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.abs_x",
                                  fill.abs.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.pos_rel_y",
                                  fill.posRel.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.pos_abs_y",
                                  fill.posAbs.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.rel_y",
                                  fill.rel.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.abs_y",
                                  fill.abs.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.angle",
                                  fill.angle, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.spread",
                                  fill.spread, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "fill.type",
                                  fill.type, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color_class",
                                  colorClass, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color.r",
                                  color.red, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color.g",
                                  color.green, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color.b",
                                  color.blue, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color.a",
                                  color.alpha, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color2.r",
                                  color2.red, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color2.g",
                                  color2.green, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color2.b",
                                  color2.blue, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color2.a",
                                  color2.alpha, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color3.r",
                                  color3.red, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color3.g",
                                  color3.green, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color3.b",
                                  color3.blue, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "color3.a",
                                  color3.alpha, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.text",
                                  text.text, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.text_class",
                                  text.textClass, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.style",
                                  text.style, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.font",
                                  text.font, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.size",
                                  text.size, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.fit_x",
                                  text.fitX, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.fit_y",
                                  text.fitY, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.min_x",
                                  text.minX, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.min_y",
                                  text.minY, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.max_x",
                                  text.maxX, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.max_y",
                                  text.maxY, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.align.x",
                                  text.align.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.align.y",
                                  text.align.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.id_source",
                                  text.idSource, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.id_text_source",
                                  text.idTextSource, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "text.elipsis",
                                  text.elipsis, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.id",
                                  gradient.id, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.type",
                                  gradient.type, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.use_rel",
                                  gradient.useRel, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel1.relative_x",
                                  gradient.rel1.relative.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel1.relative_y",
                                  gradient.rel1.relative.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel1.offset_x",
                                  gradient.rel1.offset.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel1.offset_y",
                                  gradient.rel1.offset.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel2.relative_x",
                                  gradient.rel2.relative.x, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel2.relative_y",
                                  gradient.rel2.relative.y, EET_T_DOUBLE);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel2.offset_x",
                                  gradient.rel2.offset.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartDescription,
                                  Edje_Part_Description, "gradient.rel2.offset_y",
                                  gradient.rel2.offset.y, EET_T_INT);

    NEWD("Edje_Part", Edje_Part);
    descriptorEdjePart = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "name", name, EET_T_STRING);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "id", id, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "type", type, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "effect", effect, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "mouse_events",
                                  mouseEvents, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "repeat_events",
                                  repeatEvents, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "ignore_flags",
                                  ignoreFlags, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "pointer_mode",
                                  pointerMode, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "precise_is_inside",
                                  preciseIsInside, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "clip_to_id",
                                  clipToId, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "use_alternate_font_metrics",
                                  useAlternateFontMetrics, EET_T_UCHAR);
    EET_DATA_DESCRIPTOR_ADD_SUB(descriptorEdjePart,
                                Edje_Part, "default_desc", defaultDescription,
                                descriptorEdjePartDescription);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePart,
                                 Edje_Part, "other_desc", otherDescriptions,
                                 descriptorEdjePartDescription);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.x",
                                  dragable.x, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.step_x",
                                  dragable.step.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.count_x",
                                  dragable.count.x, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.y",
                                  dragable.y, EET_T_CHAR);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.step_y",
                                  dragable.step.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.count_y",
                                  dragable.count.y, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.counfine_id",
                                  dragable.confineId, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "dragable.events_id",
                                  dragable.eventsId, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePart,
                                  Edje_Part, "source", source, EET_T_STRING);

    NEWD("Edje_Part_Collection", Edje_Part_Collection);
    descriptorEdjePartCollection  = eet_data_descriptor3_new(&eddc);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePartCollection,
                                 Edje_Part_Collection, "programs", programs,
                                 descriptorEdjeProgram);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePartCollection,
                                 Edje_Part_Collection, "parts", parts,
                                 descriptorEdjePart);
    EET_DATA_DESCRIPTOR_ADD_LIST(descriptorEdjePartCollection,
                                 Edje_Part_Collection, "data", data,
                                 descriptorEdjeData);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollection,
                                  Edje_Part_Collection, "prop.min.w",
                                  prop.min.width, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollection,
                                  Edje_Part_Collection, "prop.min.h",
                                  prop.min.height, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollection,
                                  Edje_Part_Collection, "prop.max.w",
                                  prop.max.width, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollection,
                                  Edje_Part_Collection, "prop.max.h",
                                  prop.max.height, EET_T_INT);
    EET_DATA_DESCRIPTOR_ADD_BASIC(descriptorEdjePartCollection,
                                  Edje_Part_Collection, "id", id, EET_T_INT);
}

/*!
  \internal

  Load QEdjePartDescription data from Edje_Part_Description struct.

  \todo Implement Prefered Aspect.
  \todo Implement Image Tween List.
  \todo Implement Fill Type.
*/
static void fillEdjePartDescription(QEdjePartDescription &desc,
                                    Edje_Part_Description *data)
{
    desc.state.name = data->state.name;
    desc.state.value = data->state.value;

    desc.align.setX(data->align.x);
    desc.align.setY(data->align.y);

    desc.fixedWidth = data->fixed.width;
    desc.fixedHeight = data->fixed.height;

    desc.min.setWidth(data->min.width);
    desc.min.setHeight(data->min.height);

    desc.max.setWidth(data->max.width);
    desc.max.setHeight(data->max.height);

    desc.step.setX(data->step.x);
    desc.step.setY(data->step.y);

    desc.aspect.min = data->aspect.min;
    desc.aspect.max = data->aspect.max;
    // desc.aspect.prefer = data->aspect.prefer;

    desc.imageId = data->image.id;

    if (data->image.tweenList) {
        foreach (void *item, *(data->image.tweenList)) {
            int *item_cast = (int*) item;
            desc.tweenList.append(*item_cast);
        }
    }

    desc.rel1.idX = data->rel1.idX;
    desc.rel1.idY = data->rel1.idY;
    desc.rel1.offset.setX(data->rel1.offset.x);
    desc.rel1.offset.setY(data->rel1.offset.y);
    desc.rel1.relative.setX(data->rel1.relative.x);
    desc.rel1.relative.setY(data->rel1.relative.y);

    desc.rel2.idX = data->rel2.idX;
    desc.rel2.idY = data->rel2.idY;
    desc.rel2.offset.setX(data->rel2.offset.x);
    desc.rel2.offset.setY(data->rel2.offset.y);
    desc.rel2.relative.setX(data->rel2.relative.x);
    desc.rel2.relative.setY(data->rel2.relative.y);

    // image.tween_list

    desc.gradient.id = data->gradient.id;
    desc.gradient.type = data->gradient.type;
    desc.gradient.params = data->gradient.params;
    desc.gradient.useRel = (bool)data->gradient.useRel;
    desc.gradient.rel1.offset.setX(data->gradient.rel1.offset.x);
    desc.gradient.rel1.offset.setY(data->gradient.rel1.offset.y);
    desc.gradient.rel1.relative.setX(data->gradient.rel1.relative.x);
    desc.gradient.rel1.relative.setY(data->gradient.rel1.relative.y);
    desc.gradient.rel2.offset.setX(data->gradient.rel2.offset.x);
    desc.gradient.rel2.offset.setY(data->gradient.rel2.offset.y);
    desc.gradient.rel2.relative.setX(data->gradient.rel2.relative.x);
    desc.gradient.rel2.relative.setY(data->gradient.rel2.relative.y);

    desc.border.top = data->border.top;
    desc.border.bottom = data->border.bottom;
    desc.border.left = data->border.left;
    desc.border.right = data->border.right;
    desc.border.noFill = data->border.noFill;

    desc.fill.abs.setX(data->fill.abs.x);
    desc.fill.abs.setY(data->fill.abs.y);
    desc.fill.rel.setX(data->fill.rel.x);
    desc.fill.rel.setY(data->fill.rel.y);
    desc.fill.posAbs.setX(data->fill.posAbs.x);
    desc.fill.posAbs.setY(data->fill.posAbs.y);
    desc.fill.posRel.setX(data->fill.posRel.x);
    desc.fill.posRel.setY(data->fill.posRel.y);
    desc.fill.angle = data->fill.angle;
    desc.fill.spread = data->fill.spread;
    desc.fill.smooth = data->fill.smooth;
    // fill.type

    desc.colorClass = data->colorClass;

    desc.text.text = data->text.text;
    desc.text.textClass = data->text.textClass;
    desc.text.style = data->text.style;
    desc.text.font = data->text.font;
    desc.text.align.setX(data->text.align.x);
    desc.text.align.setY(data->text.align.y);
    desc.text.elipsis = data->text.elipsis;
    desc.text.size = data->text.size;
    desc.text.idSource = data->text.idSource;
    desc.text.idTextSource = data->text.idTextSource;
    desc.text.fitX = data->text.fitX;
    desc.text.fitY = data->text.fitY;
    desc.text.minX = data->text.minX;
    desc.text.minY = data->text.minY;
    desc.text.maxX = data->text.maxX;
    desc.text.maxY = data->text.maxY;

    desc.color.setRgb(data->color.red, data->color.green,
                      data->color.blue, data->color.alpha);
    desc.color2.setRgb(data->color2.red, data->color2.green,
                       data->color2.blue, data->color2.alpha);
    desc.color3.setRgb(data->color3.red, data->color3.green,
                       data->color3.blue, data->color3.alpha);

    desc.visible = data->visible;
}

/*!
  \internal

  Returns QEdjePart instance filled with Edje_Part data.
*/
static QEdjePart *createEdjePart(Edje_Part *data)
{
    QEdjePart *part = new QEdjePart;

    part->id = data->id;
    part->name = data->name;
    part->source = data->source;
    part->effect = data->effect;
    part->mouseEvents = data->mouseEvents;
    part->repeatEvents = data->repeatEvents;
    part->preciseIsInside = data->preciseIsInside;
    part->useAlternateFontMetrics = data->useAlternateFontMetrics;
    part->clipToId = data->clipToId;
    part->dragable.x = data->dragable.x;
    part->dragable.y = data->dragable.y;
    part->dragable.step = QPoint(data->dragable.step.x,
                                 data->dragable.step.y);
    part->dragable.count = QPoint(data->dragable.count.x,
                                  data->dragable.count.y);
    part->dragable.eventsId = data->dragable.eventsId;
    part->dragable.confineId = data->dragable.confineId;

    part->type = (QEdjePart::TypeFlag) data->type;

    fillEdjePartDescription(part->defaultDescription, data->defaultDescription);

    if (data->otherDescriptions) {
        foreach (void *dt, *data->otherDescriptions) {
            QEdjePartDescription *desc = new QEdjePartDescription;
            fillEdjePartDescription(*desc, (Edje_Part_Description *) dt);
            part->otherDescriptions.append(desc);
        }
    }

    return part;
}

/*!
  \internal

  Returns QEdjeProgram instance filled with Edje_Program data.
*/
static QEdjeProgram *createEdjeProgram(Edje_Program *data)
{
    QEdjeProgram *program = new QEdjeProgram;
    program->id = data->id;
    program->name = data->name;
    program->signal = data->signal;
    program->source = data->source;

    program->inFrom = data->in.from;
    program->inRange = data->in.range;
    program->action = data->action;
    program->tweenMode = data->tween.mode;
    program->tweenTime = data->tween.time;

    if (data->state != NULL)
        program->state = data->state;

    if (data->state2 != NULL && data->action == SIGNAL_EMIT)
        program->state2 = data->state2;

    program->value = data->value;
    program->value2 = data->value2;

    if (data->targets) {
        foreach (void *dt, *data->targets)
            program->targets.append(((Edje_Program_Target *) dt)->id);
    }
    if (data->after) {
        foreach (void *dt, *data->after)
            program->after.append(((Edje_Program_After *) dt)->id);
    }
    return program;
}

/*!
  \internal

  Returns QEdjePartCollection instance filled with Edje_Part_Collection data.
*/
static QEdjePartCollection *createEdjePartCollection(Edje_Part_Collection *data)
{
    QEdjePartCollection *partcol = new QEdjePartCollection();
    partcol->id = data->id;
    partcol->part = data->part;
    partcol->propMin.setWidth(data->prop.min.width);
    partcol->propMin.setHeight(data->prop.min.height);
    partcol->propMax.setWidth(data->prop.max.width);
    partcol->propMax.setHeight(data->prop.max.height);

    if (data->parts) {
        foreach (void *dt, *data->parts) {
            QEdjePart *qpart = createEdjePart((Edje_Part *) dt);
            partcol->parts.append(qpart);
        }
    }

    if (data->programs) {
        foreach (void *dt, *data->programs) {
            QEdjeProgram *qprogram = createEdjeProgram((Edje_Program *) dt);
            partcol->programs.append(qprogram);
        }
    }

    if (data->data) {
        foreach (void *dt, *data->data) {
            QEdjeData *edata = new QEdjeData();
            edata->key = ((Edje_Data *) dt)->key;
            edata->value = ((Edje_Data *) dt)->value;
            partcol->data.append(edata);
        }
    }

    return partcol;
}

/*!
  \internal

  Returns QEdjeColorClass instance filled with Edje_Color_Class data.
*/
static QEdjeColorClass *createEdjeColorClass(Edje_Color_Class *dt)
{
    QEdjeColorClass *qcolor = new QEdjeColorClass;
    qcolor->name = dt->name;
    qcolor->color.setRgb((int)dt->r, (int)dt->g, (int)dt->b, (int)dt->a);
    qcolor->color2.setRgb((int)dt->r2, (int)dt->g2, (int)dt->b2, (int)dt->a2);
    qcolor->color3.setRgb((int)dt->r3, (int)dt->g3, (int)dt->b3, (int)dt->a3);
    return qcolor;
}

/*!
  \internal

  Returns Edje_Part_Collection instance loading it's contents from
  edje file passing the collection name.
*/
static Edje_Part_Collection *extractEdjeCollection(Edje_File *edf,
                                                   QEdjeFile *qedje_file,
                                                   const char *coll)
{
    char buf[256];
    int id = -1;
    Edje_Part_Collection *edc = NULL;

    if (edf->collectionDir) {
        foreach (void *dt, *edf->collectionDir->entries)
        {
            Edje_Part_Collection_Directory_Entry *ce;
            ce = (Edje_Part_Collection_Directory_Entry *) dt;
            if ((ce->entry) && (!strcmp(ce->entry, coll))) {
                id = ce->id;
                break;
            }
        }
    }

    if (id < 0)
        return NULL;

    snprintf(buf, sizeof(buf), "collections/%i", id);
    edc = (Edje_Part_Collection *)eet_data_read(edf->ef,
                                                descriptorEdjePartCollection, buf);
    if (!edc)
        return NULL;

    // TODO: load embryo scripts from eet

    edc->part = coll;
    edc->references = 1;

    if (!edf->collectionHash)
        edf->collectionHash = new QHash <QString, void *>();

    edf->collectionHash->insert(QString(coll), (void *)edc);

    qedje_file->collectionHash.insert(QString(coll),
                                      createEdjePartCollection(edc));

    return edc;
}

/*!
  \internal

  Returns Edje_File instance loading the data from eet file.
*/
static Edje_File *openEdjeFile(Eet_File *ef, QEdjeFile *qfile)
{
    Edje_File *edf;
    Edje_Part_Collection *edc;

    edf = (Edje_File *) eet_data_read(ef, descriptorEdjeFile, "edje_file");

    if (!edf) {
        qWarning("openEdjeFile: Corrupted edje file");
        return NULL;
    }

    edf->freeStrings = eet_dictionary_get(ef) ? 0 : 1;
    edf->ef = ef;

    if (edf->version != EDJE_FILE_VERSION) {
        // TODO: _edje_file_free(edf);
        qWarning("openEdjeFile: Incompatible edje file version");
        return NULL;
    }

    if (!edf->collectionDir) {
        // TODO: _edje_file_free(edf);
        qWarning("openEdjeFile: Corrupted collection dir");
        return NULL;
    }

    // TODO: edje textblock style parse/fix

    if (edf->data) {
        if (!edf->dataCache)
            edf->dataCache = new QHash <QString, void *>();

        foreach (void *dt, *edf->data) {
            Edje_Data *di = (Edje_Data *) dt;
            qfile->dataCache.insert(di->key, di->value);
            edf->dataCache->insert(QString(di->key), (void *) di->value);

            free(di);
        }
        delete edf->data;
        edf->data = NULL;
    }

    // add font to hash
    edf->fontHash = NULL;
    // TODO: load fonts from entries and load font hash

    if (edf->collectionDir) {
        foreach (void *dt,  *edf->collectionDir->entries) {
            Edje_Part_Collection_Directory_Entry *fde;
            fde = (Edje_Part_Collection_Directory_Entry *) dt;
            edc = extractEdjeCollection(edf, qfile, fde->entry);
        }
    }

    return edf;
}

/*!
    \class QEdjeLoader
    \brief Interface used to load edje files. It's has only 2 basic methods:
    load() and unload(). It keeps an edje file cache and is responsible to delete
    these instances when reference count reaches 0. So always remember to call
    unload when you have loaded a file.

    \code
        QEdjeFile *edf = QEdjeLoader::load("default.edj");
        // do some stuff
        QEdjeLoader::unload("default.edj");
    \endcode
*/

static bool pm_eetInitialized = false;
static QHash<QString, QEdjeFile *> pm_fileCache;

/*!
  Try to get file from cache. If not found, load it.
  Increases QEdjeFile reference count.
*/
QEdjeFile *QEdjeLoader::load(const QString &filename)
{
    QEdjeFile *edjeFile;

    if (!pm_eetInitialized) {
        setupEetDataDescriptors();
        pm_eetInitialized = true;
    }

    // need normalization and absolute path
    if (!pm_fileCache.contains(filename)) {
        // 'fn' is valid as long as 'ba' isn't deallocated
        QByteArray ba = filename.toLatin1();
        const char *fn = ba.constData();

        edjeFile = loadEdjeFile(fn);
        if (!edjeFile)
            return NULL;

        pm_fileCache.insert(filename, edjeFile);
    } else
        edjeFile = pm_fileCache.value(filename);

    edjeFile->_references++;
    return edjeFile;
}

/*!
  Update QEdjeFile reference count and unload it if it's not used anymore.
*/
void QEdjeLoader::unload(const QString &filename)
{
    QEdjeFile *edjeFile = pm_fileCache.value(filename);

    if (!edjeFile)
        return;

    qDebug() << "unloading unused edje file from cache";
    edjeFile->_references--;
    if (edjeFile->_references <= 0) {
        qDebug() << "deleting" << filename << "from cache";
        pm_fileCache.remove(filename);
        delete edjeFile;
    }
}

/*!
  Returns a QEdjeFile instance loaded from an edj file.
*/
QEdjeFile *QEdjeLoader::loadEdjeFile(const char *filename)
{
    struct stat st;
    Eet_File *eetFile;

    if (stat(filename, &st) != 0) {
        qWarning("QEdjeLoader::loadEdjeFile: File '%s' does not exist",
                 filename);
        return NULL;
    }

    eetFile = eet_open(filename, EET_FILE_MODE_READ);

    if (!eetFile) {
        qWarning("QEdjeLoader::loadEdjeFile: File '%s' has an unknown format",
                 filename);
        return NULL;
    }

    QEdjeFile *qfile = new QEdjeFile();
    Edje_File *edf = openEdjeFile(eetFile, qfile);

    if (!edf) {
        qWarning("QEdjeLoader::loadEdjeFile: Unable to open edje file '%s'",
                 filename);
        return NULL;
    }

    qfile->path = filename;
    qfile->compiler = edf->compiler;
    qfile->version = edf->version;
    qfile->featureVer = edf->featureVer;

    if (edf->data) {
        foreach (void *dt, *edf->data) {
            QEdjeData *edata = new QEdjeData();
            edata->key = ((Edje_Data *) dt)->key;
            edata->value = ((Edje_Data *) dt)->value;
            qfile->data.append(edata);
        }
    }

    if (edf->imageDir) {
        foreach (void *dd, *edf->imageDir->entries) {
            Edje_Image_Directory_Entry *fde;
            fde = (Edje_Image_Directory_Entry *) dd;

            QEdjeImageDirectoryEntry *dt = new QEdjeImageDirectoryEntry();
            dt->id = fde->id;
            dt->entry = QString(fde->entry);
            qfile->imageDir.append(dt);
        }
    }

    if (edf->collectionDir) {
        foreach (void *dd, *edf->collectionDir->entries) {
            Edje_Part_Collection_Directory_Entry *fde;
            fde = (Edje_Part_Collection_Directory_Entry *) dd;

            QEdjePartCollectionDirectoryEntry *dt =
                new QEdjePartCollectionDirectoryEntry();
            dt->id = fde->id;
            dt->entry = fde->entry;
            qfile->collectionDir.append(dt);
        }
    }

    if (edf->styles) {
        foreach (void *dd, *edf->styles) {
            Edje_Style *fde;
            Edje_Style_Tag *tag;
            fde = (Edje_Style *) dd;

            QEdjeStyle *dt = new QEdjeStyle;
            dt->name = fde->name;

            if (fde->tags)
            foreach (void *dd, *fde->tags) {
                tag = (Edje_Style_Tag*) dd;
                dt->addTag(tag->key, tag->value, tag->font,
                           tag->fontSize, tag->textClass);
            }
            qfile->styles.append(dt);
        }
    }

    if (edf->colorClasses) {
        foreach (void *dd, *edf->colorClasses) {
            Edje_Color_Class *fde = (Edje_Color_Class *) dd;
            qfile->colorClasses.append(createEdjeColorClass(fde));
        }
    }
    eet_close(eetFile);

    return qfile;
}

QEdjeFile::~QEdjeFile()
{
    qDeleteAll(fontDir);
    qDeleteAll(imageDir);
    qDeleteAll(collectionHash);
    qDeleteAll(collectionDir);
    qDeleteAll(data);
    qDeleteAll(styles);
    qDeleteAll(colorClasses);
}
