#include "imageobj.h"

#include "file.h"
#include "mapobj.h"

#include <QDebug>
#include <QDir>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QSvgGenerator>

extern QDir cacheDir;
extern ulong imageLastID;

/////////////////////////////////////////////////////////////////
// ImageObj
/////////////////////////////////////////////////////////////////
ImageObj::ImageObj()
{
    // qDebug() << "Const ImageObj ()  this=" << this;
    init();
}

ImageObj::ImageObj(QGraphicsItem *parent) : QGraphicsItem(parent)
{
    // qDebug() << "Const ImageObj  this=" << this << "  parent= " << parent ;
    init();
}

ImageObj::~ImageObj()
{
    // qDebug() << "Destr ImageObj  this=" << this << "  imageType = " <<
    // imageType ;
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        if (svgItem)
            delete (svgItem);
        break;
    case ImageObj::Pixmap:
        if (pixmapItem)
            delete (pixmapItem);
        break;
    default:
        qDebug() << "Destr ImgObj: imageType undefined";
        break;
    }
}

void ImageObj::init()
{
    // qDebug() << "Const ImageObj (scene)";
    hide();

    // Assign ID
    imageLastID++;
    imageID = imageLastID;

    imageType = ImageObj::Undefined;
    svgItem = NULL;
    pixmapItem = NULL;
    scaleFactor = 1;
}

void ImageObj::copy(ImageObj *other)
{
    prepareGeometryChange();
    if (imageType != ImageObj::Undefined)
        qWarning() << "ImageObj::copy into existing image of type "
                   << imageType;

    switch (other->imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        if (!other->svgCachePath.isEmpty()) {
            load(other->svgCachePath, true);
        }
        else
            qWarning() << "ImgObj::copy svg: no svgCachePath available.";

        svgItem->setVisible(isVisible());
        break;
    case ImageObj::Pixmap:
        pixmapItem = new QGraphicsPixmapItem();
        pixmapItem->setPixmap(other->pixmapItem->pixmap());
        pixmapItem->setParentItem(parentItem());
        pixmapItem->setVisible(isVisible());
        imageType = ImageObj::Pixmap;
        break;
    default:
        qWarning() << "ImgObj::copy other->imageType undefined";
        return;
        break;
    }
    setScaleFactor(other->scaleFactor);
}

void ImageObj::setPos(const QPointF &pos)
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        svgItem->setPos(pos);
        break;
    case ImageObj::Pixmap:
        pixmapItem->setPos(pos);
        break;
    default:
        break;
    }
}

void ImageObj::setPos(const qreal &x, const qreal &y) { setPos(QPointF(x, y)); }

void ImageObj::setZValue(qreal z)
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        svgItem->setZValue(z);
        break;
    case ImageObj::Pixmap:
        pixmapItem->setZValue(z);
        break;
    default:
        break;
    }
}

void ImageObj::setVisibility(bool v)
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        v ? svgItem->show() : svgItem->hide();
        break;
    case ImageObj::Pixmap:
        v ? pixmapItem->show() : pixmapItem->hide();
        break;
    default:
        break;
    }
}

void ImageObj::setWidth(qreal w)
{
    if (boundingRect().width() == 0)
        return;

    setScaleFactor(w / boundingRect().width());
}

void ImageObj::setScaleFactor(qreal f)
{
    scaleFactor = f;
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        svgItem->setScale(f);
        break;
    case ImageObj::Pixmap:
        if (f != 1)
            pixmapItem->setScale(f);
        break;
    default:
        break;
    }
}

qreal ImageObj::getScaleFactor() { return scaleFactor; }

QRectF ImageObj::boundingRect() const
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        return svgItem->mapToScene(svgItem->boundingRect()).boundingRect();
    case ImageObj::Pixmap:
        return pixmapItem->mapToScene(pixmapItem->boundingRect()).boundingRect();
    default:
        break;
    }
    return QRectF();
}

void ImageObj::paint(QPainter *painter, const QStyleOptionGraphicsItem *sogi,
                     QWidget *widget)
{
    // Not really called, but required because paint is pure virtual in
    // QGraphicsItem

    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        svgItem->paint(painter, sogi, widget);
        break;
    case ImageObj::Pixmap:
        pixmapItem->paint(painter, sogi, widget);
        break;
    default:
        break;
    }
}

bool ImageObj::load(const QString &fn, bool createClone)
{
    // createClone == true, if called via copy()

    if (imageType != ImageObj::Undefined) {
        qWarning() << "ImageObj::load (" << fn
                   << ") into existing image of type " << imageType;
        return false;
    }

    if (fn.toLower().endsWith(".svg")) {
        svgItem = new QGraphicsSvgItem(fn);
        if (scene())
            scene()->addItem(svgItem);

        if (createClone) {
            imageType = ImageObj::ClonedSVG;
            svgCachePath = fn;
        }
        else {
            imageType = ImageObj::SVG;

            // Copy original file to cache
            QFile svgFile(fn);
            QString newPath = cacheDir.path() + "/" + QString().number(imageID) +
                              "-" + basename(fn);
            if (!svgFile.copy(newPath)) {
                qWarning() << "ImageObj::load (" << fn
                           << ") could not be copied to " << newPath;
            }

            svgCachePath = newPath;
        }

        return true;
    }
    else {
        QPixmap pm;
        if (pm.load(fn)) {
            prepareGeometryChange();

            if (pixmapItem)
                qWarning() << "ImageObj::load " << fn
                           << "pixmapIteam already exists";
            pixmapItem = new QGraphicsPixmapItem(this);
            pixmapItem->setPixmap(pm);
            pixmapItem->setParentItem(parentItem());
            imageType = ImageObj::Pixmap;

            return true;
        }
    }

    return false;
}

bool ImageObj::save(const QString &fn)
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        if (svgItem) {
            QFile svgFile(svgCachePath);
            if (!QFile(fn).exists() && !svgFile.copy(fn)) {
                qWarning() << "ImageObj::save  failed to copy " << svgCachePath
                           << " to " << fn;
                return false;
            }
        }
        return true;
        break;
    case ImageObj::Pixmap:
        return pixmapItem->pixmap().save(fn, "PNG", 100);
        break;
    default:
        break;
    }
    return false;
}

QString ImageObj::getExtension()
{
    QString s;
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        s = ".svg";
        break;
    case ImageObj::Pixmap:
        s = ".png";
        break;
    default:
        break;
    }
    return s;
}

ImageObj::ImageType ImageObj::getType() { return imageType; }

QIcon ImageObj::getIcon()
{
    switch (imageType) {
    case ImageObj::SVG:
    case ImageObj::ClonedSVG:
        return QPixmap(svgCachePath);
        break;
    case ImageObj::Pixmap:
        return QIcon(pixmapItem->pixmap());
        break;
    default:
        break;
    }
    return QIcon();
}
