/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkEncodedInfo_DEFINED
#define SkEncodedInfo_DEFINED

#include "include/core/SkAlphaType.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkTypes.h"
#include "include/private/SkAPI.h"
#include "include/private/SkHdrMetadata.h"
#include "include/private/SkTo.h"
#include "modules/skcms/skcms.h"

#include <cstdint>
#include <memory>
#include <tuple>
#include <utility>

namespace SkCodecs {
class ColorProfile;
}

struct SK_API SkEncodedInfo {
public:
    enum Alpha {
        kOpaque_Alpha,
        kUnpremul_Alpha,

        // Each pixel is either fully opaque or fully transparent.
        // There is no difference between requesting kPremul or kUnpremul.
        kBinary_Alpha,
    };

    /*
     * We strive to make the number of components per pixel obvious through
     * our naming conventions.
     * Ex: kRGB has 3 components.  kRGBA has 4 components.
     *
     * This sometimes results in redundant Alpha and Color information.
     * Ex: kRGB images must also be kOpaque.
     */
    enum Color {
        // PNG, WBMP
        kGray_Color,

        // PNG
        kGrayAlpha_Color,

        // PNG with Skia-specific sBIT
        // Like kGrayAlpha, except this expects to be treated as
        // kAlpha_8_SkColorType, which ignores the gray component. If
        // decoded to full color (e.g. kN32), the gray component is respected
        // (so it can share code with kGrayAlpha).
        kXAlpha_Color,

        // PNG
        // 565 images may be encoded to PNG by specifying the number of
        // significant bits for each channel.  This is a strange 565
        // representation because the image is still encoded with 8 bits per
        // component.
        k565_Color,

        // PNG, GIF, BMP
        kPalette_Color,

        // PNG, RAW
        kRGB_Color,
        kRGBA_Color,

        // BMP
        kBGR_Color,
        kBGRX_Color,
        kBGRA_Color,

        // JPEG, WEBP
        kYUV_Color,

        // WEBP
        kYUVA_Color,

        // JPEG
        // Photoshop actually writes inverted CMYK data into JPEGs, where zero
        // represents 100% ink coverage.  For this reason, we treat CMYK JPEGs
        // as having inverted CMYK.  libjpeg-turbo warns that this may break
        // other applications, but the CMYK JPEGs we see on the web expect to
        // be treated as inverted CMYK.
        kInvertedCMYK_Color,
        kYCCK_Color,
    };

    static SkEncodedInfo Make(
        int width, int height, Color color, Alpha alpha, int bitsPerComponent);

    static SkEncodedInfo Make(
        int width, int height, Color color, Alpha alpha, int bitsPerComponent,
        std::unique_ptr<SkCodecs::ColorProfile> profile);

    static SkEncodedInfo Make(
        int width, int height, Color color, Alpha alpha, int bitsPerComponent,
        std::unique_ptr<SkCodecs::ColorProfile> profile, int colorDepth);

    static SkEncodedInfo Make(
        int width, int height, Color color, Alpha alpha, int bitsPerComponent,
        int colorDepth,
        std::unique_ptr<SkCodecs::ColorProfile> profile, const skhdr::Metadata& hdrMetadata);

    /*
     * Returns a recommended SkImageInfo.
     *
     * TODO: Leave this up to the client.
     */
    SkImageInfo makeImageInfo() const;

    int   width() const { return fWidth;  }
    int  height() const { return fHeight; }
    Color color() const { return fColor;  }
    Alpha alpha() const { return fAlpha;  }
    bool opaque() const { return fAlpha == kOpaque_Alpha; }

    // TODO(https://issues.skia.org/issues/464217864): Remove direct access to the
    // skcms_ICCProfile and change profileData() to serialize a new profile.
    const skcms_ICCProfile* profile() const;
    sk_sp<const SkData> profileData() const;
    const SkCodecs::ColorProfile* colorProfile() const {
        return fColorProfile.get();
    }

    uint8_t bitsPerComponent() const { return fBitsPerComponent; }

    uint8_t bitsPerPixel() const {
        switch (fColor) {
            case kGray_Color:
                return fBitsPerComponent;
            case kXAlpha_Color:
            case kGrayAlpha_Color:
                return 2 * fBitsPerComponent;
            case kPalette_Color:
                return fBitsPerComponent;
            case kRGB_Color:
            case kBGR_Color:
            case kYUV_Color:
            case k565_Color:
                return 3 * fBitsPerComponent;
            case kRGBA_Color:
            case kBGRA_Color:
            case kBGRX_Color:
            case kYUVA_Color:
            case kInvertedCMYK_Color:
            case kYCCK_Color:
                return 4 * fBitsPerComponent;
        }
        SkASSERT(false);
        return 0;
    }

    SkEncodedInfo(const SkEncodedInfo& orig) = delete;
    SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;

    SkEncodedInfo(SkEncodedInfo&& orig);
    SkEncodedInfo& operator=(SkEncodedInfo&&);

    // Explicit copy method, to avoid accidental copying.
    SkEncodedInfo copy() const;

    // Return number of bits of R/G/B channel
    uint8_t getColorDepth() const {
        return fColorDepth;
    }

    // Return the HDR metadata associated with this image. Note that even SDR images can include
    // HDR metadata (e.g, indicating how to inverse tone map when displayed on an HDR display).
    const skhdr::Metadata& getHdrMetadata() const {
        return fHdrMetadata;
    }

    ~SkEncodedInfo();

private:
    SkEncodedInfo(
        int width, int height, Color color, Alpha alpha, uint8_t bitsPerComponent,
        uint8_t colorDepth,
        std::unique_ptr<SkCodecs::ColorProfile> profile, const skhdr::Metadata& hdrMetadata);

    static void VerifyColor(Color color, Alpha alpha, int bitsPerComponent) {
        // Avoid `-Wunused-parameter` warnings on non-debug builds.
        std::ignore = alpha;
        std::ignore = bitsPerComponent;

        switch (color) {
            case kGray_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                return;
            case kGrayAlpha_Color:
                SkASSERT(kOpaque_Alpha != alpha);
                return;
            case kPalette_Color:
                SkASSERT(16 != bitsPerComponent);
                return;
            case kRGB_Color:
            case kBGR_Color:
            case kBGRX_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                SkASSERT(bitsPerComponent >= 8);
                return;
            case kYUV_Color:
            case kInvertedCMYK_Color:
            case kYCCK_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                SkASSERT(8 == bitsPerComponent);
                return;
            case kRGBA_Color:
                SkASSERT(bitsPerComponent >= 8);
                return;
            case kBGRA_Color:
            case kYUVA_Color:
                SkASSERT(8 == bitsPerComponent);
                return;
            case kXAlpha_Color:
                SkASSERT(kUnpremul_Alpha == alpha);
                SkASSERT(8 == bitsPerComponent);
                return;
            case k565_Color:
                SkASSERT(kOpaque_Alpha == alpha);
                SkASSERT(8 == bitsPerComponent);
                return;
        }
        SkASSERT(false);  // Unrecognized `color` enum value.
    }

    int     fWidth;
    int     fHeight;
    Color   fColor;
    Alpha   fAlpha;
    uint8_t fBitsPerComponent;
    uint8_t fColorDepth;
    std::unique_ptr<const SkCodecs::ColorProfile> fColorProfile;
    skhdr::Metadata                               fHdrMetadata;
};

#endif
