/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2008-03-13
 * Description : image files selector dialog.
 * 
 * Copyright (C) 2008 by Gilles Caulier <caulier dot gilles at gmail dot com> 
 *
 * This program 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 2, or (at your option)
 * any later version.
 * 
 * This program 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.
 *
 * ============================================================ */

// TQt includes.

#include <tqlabel.h>
#include <tqlayout.h>
#include <tqguardedptr.h>
#include <tqtimer.h>

// KDE includes.

#include <tdeapplication.h>
#include <tdelocale.h>
#include <tdestandarddirs.h>
#include <tdefiledialog.h>
#include <kimageio.h>
#include <kiconloader.h>

// LibKDcraw includes.

#include <libkdcraw/version.h>
#include <libkdcraw/kdcraw.h>

#if KDCRAW_VERSION < 0x000106
#include <libkdcraw/dcrawbinary.h>
#endif

// Local includes.

#include "ddebug.h"
#include "dmetadata.h"
#include "thumbnailsize.h"
#include "thumbnailjob.h"
#include "imagedialog.h"
#include "imagedialog.moc"

namespace Digikam
{

class ImageDialogPreviewPrivate 
{

public:

    ImageDialogPreviewPrivate()
    {
        imageLabel = 0;
        infoLabel  = 0;
        thumbJob   = 0;
        timer      = 0;
    }

    TQTimer                    *timer;

    TQLabel                    *imageLabel;
    TQLabel                    *infoLabel;

    KURL                       currentURL;

    DMetadata                  metaIface;

    TQGuardedPtr<ThumbnailJob>  thumbJob;
};

ImageDialogPreview::ImageDialogPreview(TQWidget *parent)
                  : KPreviewWidgetBase(parent)
{
    d = new ImageDialogPreviewPrivate;

    TQVBoxLayout *vlay = new TQVBoxLayout(this);
    d->imageLabel     = new TQLabel(this);
    d->imageLabel->setAlignment(TQt::AlignHCenter | TQt::AlignVCenter);
    d->imageLabel->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding));

    d->infoLabel = new TQLabel(this);

    vlay->setMargin(0);
    vlay->setSpacing(KDialog::spacingHint());
    vlay->addWidget(d->imageLabel);
    vlay->addWidget(d->infoLabel);

    setSupportedMimeTypes(KImageIO::mimeTypes());

    d->timer = new TQTimer(this);

    connect(d->timer, TQ_SIGNAL(timeout()), 
            this, TQ_SLOT(showPreview()) );
}

ImageDialogPreview::~ImageDialogPreview() 
{
    if (!d->thumbJob.isNull())
    {
        d->thumbJob->kill();
        d->thumbJob = 0;
    }
    delete d;
}

TQSize ImageDialogPreview::sizeHint() const
{
    return TQSize(256, 256);
}

void ImageDialogPreview::resizeEvent(TQResizeEvent *)
{
    d->timer->start(100, true);
}

void ImageDialogPreview::showPreview()
{
    KURL url(d->currentURL);
    clearPreview();
    showPreview(url);
}

void ImageDialogPreview::showPreview(const KURL& url)
{
    if (!url.isValid()) 
    {
        clearPreview();
        return;
    }

    if (url != d->currentURL) 
    {
        clearPreview();
        d->currentURL = url;

        if (!d->thumbJob.isNull())
        {
        d->thumbJob->kill();
        d->thumbJob = 0;
        }

        d->thumbJob = new ThumbnailJob(url, ThumbnailSize::Huge, true, true);

        connect(d->thumbJob, TQ_SIGNAL(signalThumbnail(const KURL&, const TQPixmap&)),
                this, TQ_SLOT(slotGotThumbnail(const KURL&, const TQPixmap&)));

        connect(d->thumbJob, TQ_SIGNAL(signalFailed(const KURL&)),
                this, TQ_SLOT(slotFailedThumbnail(const KURL&)));

        d->metaIface.load(d->currentURL.path());
        PhotoInfoContainer info = d->metaIface.getPhotographInformations();
        if (!info.isEmpty())
        {
            TQString identify;
            TQString make, model, dateTime, aperture, focalLength, exposureTime, sensitivity;
            TQString unavailable(i18n("<i>unavailable</i>"));
            TQString cellBeg("<tr><td><nobr><font size=-1>");
            TQString cellMid("</font></nobr></td><td><nobr><font size=-1>");
            TQString cellEnd("</font></nobr></td></tr>");

            if (info.make.isEmpty()) make = unavailable;
            else make = info.make;

            if (info.model.isEmpty()) model = unavailable;
            else model = info.model;

            if (!info.dateTime.isValid()) dateTime = unavailable;
            else dateTime = TDEGlobal::locale()->formatDateTime(info.dateTime, true, true);

            if (info.aperture.isEmpty()) aperture = unavailable; 
            else aperture = info.aperture;

            if (info.focalLength.isEmpty()) focalLength = unavailable; 
            else focalLength = info.focalLength;

            if (info.exposureTime.isEmpty()) exposureTime = unavailable; 
            else exposureTime = info.exposureTime;

            if (info.sensitivity.isEmpty()) sensitivity = unavailable; 
            else sensitivity = i18n("%1 ISO").arg(info.sensitivity);

            identify = "<table cellspacing=0 cellpadding=0>";
            identify += cellBeg + i18n("Make:")        + cellMid + make         + cellEnd;
            identify += cellBeg + i18n("Model:")       + cellMid + model        + cellEnd;
            identify += cellBeg + i18n("Created:")     + cellMid + dateTime     + cellEnd;
            identify += cellBeg + i18n("Aperture:")    + cellMid + aperture     + cellEnd;
            identify += cellBeg + i18n("Focal:")       + cellMid + focalLength  + cellEnd;
            identify += cellBeg + i18n("Exposure:")    + cellMid + exposureTime + cellEnd;
            identify += cellBeg + i18n("Sensitivity:") + cellMid + sensitivity  + cellEnd;
            identify += "</table>";

            d->infoLabel->setText(identify);
        }
        else
            d->infoLabel->clear();
    }
}

void ImageDialogPreview::slotGotThumbnail(const KURL& url, const TQPixmap& pix)
{
    if (url == d->currentURL)
    {
        TQPixmap pixmap;
        TQSize s = d->imageLabel->contentsRect().size();

        if (s.width() < pix.width() || s.height() < pix.height())
            pixmap = pix.convertToImage().smoothScale(s, TQImage::ScaleMin);
        else 
            pixmap = pix;

        d->imageLabel->setPixmap(pixmap);
    }
}

void ImageDialogPreview::slotFailedThumbnail(const KURL& /*url*/)
{
    TDEIconLoader* iconLoader = tdeApp->iconLoader();
    d->imageLabel->setPixmap(iconLoader->loadIcon("image-x-generic", TDEIcon::NoGroup, 128,
                             TDEIcon::DefaultState, 0, true));
}

void ImageDialogPreview::clearPreview()
{
    d->imageLabel->clear();
    d->infoLabel->clear();
    d->currentURL = KURL();
}

// ------------------------------------------------------------------------

class ImageDialogPrivate 
{

public:

    ImageDialogPrivate()
    {
        singleSelect = false;
    }

    bool       singleSelect;

    TQString    fileformats;

    KURL       url;
    KURL::List urls;
};

ImageDialog::ImageDialog(TQWidget* parent, const KURL &url, bool singleSelect, const TQString& caption)
{
    d = new ImageDialogPrivate;
    d->singleSelect = singleSelect;

    TQStringList patternList = TQStringList::split('\n', KImageIO::pattern(KImageIO::Reading));

    // All Images from list must been always the first entry given by KDE API
    TQString allPictures = patternList[0];

#if KDCRAW_VERSION < 0x000106
    // Add other files format witch are missing to All Images" type mime provided by KDE and remplace current.
    if (KDcrawIface::DcrawBinary::instance()->versionIsRight())
    {
        allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::DcrawBinary::instance()->rawFiles()) + TQString(" *.JPE *.TIF"));
        patternList.remove(patternList[0]);
        patternList.prepend(allPictures);
        // Added RAW file formats supported by dcraw program like a type mime. 
        // Nota: we cannot use here "image/x-raw" type mime from KDE because it uncomplete 
        // or unavailable (see file #121242 in B.K.O).
        patternList.append(i18n("\n%1|Camera RAW files").arg(TQString(KDcrawIface::DcrawBinary::instance()->rawFiles())));
    }
#else
    allPictures.insert(allPictures.find("|"), TQString(KDcrawIface::KDcraw::rawFiles()) + TQString(" *.JPE *.TIF"));
    patternList.remove(patternList[0]);
    patternList.prepend(allPictures);
    // Added RAW file formats supported by dcraw program like a type mime. 
    // Nota: we cannot use here "image/x-raw" type mime from KDE because it uncomplete 
    // or unavailable (see file #121242 in B.K.O).
    patternList.append(i18n("\n%1|Camera RAW files").arg(TQString(KDcrawIface::KDcraw::rawFiles())));
#endif

    d->fileformats = patternList.join("\n");

    DDebug() << "fileformats=" << d->fileformats << endl;

    KFileDialog dlg(url.path(), d->fileformats, parent, "imageFileOpenDialog", false);
    ImageDialogPreview *preview = new ImageDialogPreview(&dlg);
    dlg.setPreviewWidget(preview);
    dlg.setOperationMode(KFileDialog::Opening);

    if (d->singleSelect)
    {
        dlg.setMode(KFile::File);
        if (caption.isEmpty()) dlg.setCaption(i18n("Select an Image"));
        else dlg.setCaption(caption);
        dlg.exec();
        d->url = dlg.selectedURL();
    }
    else
    {
        dlg.setMode(KFile::Files);
        if (caption.isEmpty()) dlg.setCaption(i18n("Select Images"));
        else dlg.setCaption(caption);
        dlg.exec();
        d->urls = dlg.selectedURLs();
    }
}

ImageDialog::~ImageDialog() 
{
    delete d;
}

bool ImageDialog::singleSelect() const 
{
    return d->singleSelect;
}

TQString ImageDialog::fileformats() const 
{
    return d->fileformats;
}

KURL ImageDialog::url() const
{
    return d->url;
}

KURL::List ImageDialog::urls() const
{
    return d->urls;
}

KURL::List ImageDialog::getImageURLs(TQWidget* parent, const KURL& url, const TQString& caption)
{
    ImageDialog dlg(parent, url, false, caption);
    if (!dlg.urls().isEmpty())
        return dlg.urls();
    else
        return KURL::List();
}

KURL ImageDialog::getImageURL(TQWidget* parent, const KURL& url, const TQString& caption)
{
    ImageDialog dlg(parent, url, true, caption);
    if (dlg.url() != KURL())
        return dlg.url();
    else
        return KURL();
}

} // namespace Digikam
