/* ============================================================
 *
 * This file is a part of digiKam project
 * https://www.digikam.org
 *
 * Date        : 2004-02-14
 * Description : image data interface for image tools
 *
 * Copyright (C) 2004-2005 by Renchi Raju <renchi dot raju at gmail dot com>
 * Copyright (C) 2004-2022 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.
 *
 * ============================================================ */

#ifndef DIGIKAM_IMAGE_IFACE_H
#define DIGIKAM_IMAGE_IFACE_H

// Qt includes

#include <QString>
#include <QPixmap>

// Local includes

#include "dimg.h"
#include "dcolor.h"
#include "filteraction.h"
#include "photoinfocontainer.h"
#include "digikam_export.h"

class QPaintDevice;

namespace Digikam
{

class DIGIKAM_EXPORT ImageIface
{

public:

    enum PreviewType
    {
        FullImage,      ///< Preview will be rendered using full image.
        ImageSelection  ///< Preview will be rendered using current selection from editor canvas.
    };

public:

    /**
     * Standard constructor. Size is the constrain dimension of preview. This can be null size.
     */
    explicit ImageIface(const QSize& size = QSize(0, 0));
    ~ImageIface();

    /**
     * If useSelection is true, preview will be rendered using current selection in editor instead the full
     * image. Default preview is FullImage.
     */
    void setPreviewType(PreviewType type = FullImage);

    /**
     * Sets preview size and returns new preview as with getPreview.
     * The parameters are only hints, previewSize() may differ from size.
     */
    DImg  setPreviewSize(const QSize& size)                 const;

    /**
     * Methods to get/set preview image information.
     */
    QSize       previewSize()                               const;
    bool        previewHasAlpha()                           const;
    bool        previewSixteenBit()                         const;
    PreviewType previewType()                               const;

    /**
     * Return a pointer to the DImg object representing the preview image.
     *  This function is a backdoor for preview editing.
     */
    DImg* previewReference();

    /**
     * Return a DImg object representing the preview image.
     */
    DImg  preview()                                         const;

    /**
     * Return current image selection position and size into original image coordinates.
     */
    QRect selectionRect()                                   const;

    /**
     * Return a DImg object representing the current original image selection.
     */
    DImg  selection()                                       const;

    /**
     * Crop the original image currently hosted by editor to the region.
     */
    void crop(const QRect& region);

    /**
     * Get colors from original, (unchanged) preview
     * or target preview (set by setPreviewImage) image.
     */
    DColor colorInfoFromOriginal(const QPoint& point)       const;
    DColor colorInfoFromPreview(const QPoint& point)        const;
    DColor colorInfoFromTargetPreview(const QPoint& point)  const;

    /**
     * Methods to get/set original image information.
     */
    QSize originalSize()                                    const;
    bool  originalHasAlpha()                                const;
    bool  originalSixteenBit()                              const;

    /**
     * Original image meta-data management methods.
     */
    IccProfile         originalIccProfile()                 const;
    PhotoInfoContainer originalPhotoInfo()                  const;
    MetaEngineData     originalMetadata()                   const;
    void               setOriginalMetadata(const MetaEngineData& meta);

    /**
     * Return a pointer to the DImg object representing the original image.
     * This object may not be modified or stored. Make copies if you need.
     */
    DImg* original()                                        const;

    /**
     * Convert depth of original image.
     */
    void convertOriginalColorDepth(int depth);

    /**
     * Convert a DImg image to a pixmap for screen using color
     * managed view if necessary.
     */
    QPixmap convertToPixmap(const DImg& img)                const;

    /**
     * Paint the current target preview image (or the preview image,
     * if setPreview has not been called) on the given paint device.
     * at x|y, with given maximum width and height taken from rectangle rect.
     */
    void paint(QPaintDevice* const device, const QRect& rect, QPainter* const painter = nullptr);

    /**
     * Set the color profile of the original image.
     */
    void setOriginalIccProfile(const IccProfile& profile);

    /**
     * Set the color profile of the preview image.
     */
    void setPreviewIccProfile(const IccProfile& profile);

    /**
     * Replace the data of the current original image selection with the given data.
     * The characteristics of the data must match the characteristics of the current
     * selection as returned by the selectionWidth(), selectionHeight(),
     * originalSixteenBit() and originalHasAlpha() methods.
     * Caller is an i18n'ed string that will be shown as the undo/redo action name.
     */
    void setSelection(const QString& caller, const FilterAction& action, const DImg& img);

    /**
     * Replace the stored target preview with the given image.
     * The characteristics of the data must match the characteristics of the current
     * as returned by the preview...() methods.
     * The target preview image is used by the paint() and
     * colorInfoFromTargetPreview() methods.
     * The image returned by getPreview() is unaffected.
     */
    void setPreview(const DImg& img);

    /**
     * Replace the data of the original with the given image.
     * The characteristics of the data must match the characteristics of
     * the original image as returned by the original...() methods,
     * The size of image can be changed.
     * Caller is an i18n'ed string that will be shown as the undo/redo action name.
     */
    void setOriginal(const QString& caller, const FilterAction& action, const DImg& img);

private:

    // Disable
    ImageIface(const ImageIface&)            = delete;
    ImageIface& operator=(const ImageIface&) = delete;

private:

    class Private;
    Private* const d;
};

} // namespace Digikam

#endif // DIGIKAM_IMAGE_IFACE_H
