/*
 * 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 <Eet.h>
#include <QDebug>
#include <QPixmapCache>
#include <QRegion>
#include <QPainter>
#include <QPaintEvent>

#include "qedjeimage.h"

/*!
    \class QEdjeImage
    \brief A pixmap that uses internal image cache.

    A QEdjeImage is a pixmap that can be loaded from an edj file
    and placed in a canvas.
*/


#define DATA32 unsigned int

/*!
    Constructs a QEdjeImage with empty pixmap.
*/
QEdjeImage::QEdjeImage(QZionAbstractCanvas *canvas)
    : QZionImage(canvas)
{

}

/*!
    Constructs a QEdjeImage with specified image.

    The filepath must be a valid edj file and the key a valid image key
    inside this edj file.
*/
QEdjeImage::QEdjeImage(QZionAbstractCanvas *canvas,
                       const QString &filepath, const QString &key)
    : QZionImage(canvas)
{
    if (key == "images/-1") {
        clear();
        return;
    }

    if (!load(filepath, key)) {
        qCritical("Error loading image data \"%s\" from \"%s\"",
                  key.toLatin1().data(), filepath.toLatin1().data());
    }
}

/*!
  Load an image from a edj file.
  You must specify the edj filepath and the image key.

  \code
        QEdjeImage im(canvas);
        im.load("default.edj", "images/1");
  \endcode
*/
bool QEdjeImage::load(const QString &filename, const QString &key)
{
    if (_filepath == filename && _key == key)
        return true;

    _key = key;
    _filepath = filename;

    QPixmap result;
    QString token = filename + ":" + key;

    if (QPixmapCache::find(token, result)) {
        setPixmap(result);
        return true;
    }

    result = loadPixmapFromEetFile(filename, key);

    if (result.isNull()) {
        clear();
        return false;
    }

    QPixmapCache::insert(token, result);
    setPixmap(result);

    return true;
}

/*!
  Reload the image (force cache update)
*/
bool QEdjeImage::reload()
{
    if (pixmap().isNull())
        return true;

    QPixmap result;
    result = loadPixmapFromEetFile(_filepath, _key);
    if (result.isNull()) {
        clear();
        return false;
    }

    QString token = _filepath + ":" + _key;
    QPixmapCache::insert(token, result);
    QZionImageBorder b = border();
    setPixmap(result);
    setBorder(b);

    return true;
}

/*!
  \internal

  Load an image from an edj file looking for it's key.

  \todo Check loading performance (ref. evas_image_load_file_data_eet)
*/
QPixmap QEdjeImage::loadPixmapFromEetFile(const QString &filename,
                                          const QString &fkey)
{
    int maxlen = 400;
    char file[maxlen], key[maxlen];

    if (filename.size() >= maxlen || fkey.size() >= maxlen) {
        qCritical("Filename or key too long.");
        return QPixmap();
    }

    strncpy(file, filename.toLatin1().data(), filename.size() + 1);
    strncpy(key, fkey.toLatin1().data(), fkey.size() + 1);

    Eet_File *ef = eet_open(file, EET_FILE_MODE_READ);
    if (!ef) {
        qCritical("Could not open edj file");
        return QPixmap();
    }

    unsigned int w, h;
    int alpha, compression, quality, lossy;

    DATA32 *body = (DATA32 *)eet_data_image_read(ef, key, &w, &h,
                                                 &alpha, &compression,
                                                 &quality, &lossy);

    eet_close(ef);

    if (!body) {
        qCritical("Could not load image from edj file");
        return QPixmap();
    }

    if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192)) {
        free(body);
        qCritical("Invalid image dimension");
        return QPixmap();
    }

    // edje compiled images are premultiplied
    QImage image = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
    memcpy(image.bits(), body, w * h * sizeof(DATA32));

    free(body);

    return QPixmap::fromImage(image);
}
