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

#include "include/core/SkTypes.h"
#ifdef SK_ENABLE_NDK_IMAGES
#include "include/codec/SkEncodedImageFormat.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkImageGenerator.h"
#include "include/core/SkStream.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/encode/SkPngEncoder.h"
#include "include/encode/SkWebpEncoder.h"
#include "include/private/base/SkMalloc.h"
#include "src/image/SkImageGeneratorPriv.h"
#include "tests/Test.h"
#include "tools/Resources.h"
#include "tools/ToolUtils.h"

#include <stdint.h>
#include <vector>

static const char* kPng          = "png";
static const char* kJpeg         = "jpeg";
static const char* kWebpLossless = "webp_lossless";
static const char* kWebpLossy    = "webp_lossy";

namespace {
static const struct {
    SkEncodedImageFormat format;
    int                  quality;
    const char*          name;
} gRecs[] = {
    { SkEncodedImageFormat::kPNG,  100, kPng},
    { SkEncodedImageFormat::kJPEG, 100, kJpeg},
    { SkEncodedImageFormat::kWEBP, 100, kWebpLossless},
    { SkEncodedImageFormat::kWEBP,  80, kWebpLossy},
};
}

static sk_sp<SkData> encode_ndk(const SkPixmap& pmap, SkEncodedImageFormat format, int quality) {
    SkDynamicMemoryWStream stream;
    SkDynamicMemoryWStream buf;
    switch (format) {
        case SkEncodedImageFormat::kPNG: {
            bool success = SkPngEncoder::Encode(&buf, pmap, {});
            return success ? buf.detachAsData() : nullptr;
        }
        case SkEncodedImageFormat::kJPEG: {
            SkJpegEncoder::Options opts;
            opts.fQuality = quality;
            bool success = SkJpegEncoder::Encode(&buf, pmap, opts);
            return success ? buf.detachAsData() : nullptr;
        }
        case SkEncodedImageFormat::kWEBP: {
            SkWebpEncoder::Options opts;
            opts.fQuality = quality;
            bool success = SkWebpEncoder::Encode(&buf, pmap, opts);
            return success ? buf.detachAsData() : nullptr;
        }
        default:
            SkUNREACHABLE;
    }
}

DEF_TEST(NdkEncode, r) {
    for (auto ct : { kRGBA_8888_SkColorType,
                     kRGB_565_SkColorType,
                     kRGBA_F16_SkColorType }) {
        SkBitmap bm;
        bm.allocPixels(SkImageInfo::Make(10, 10, ct, kOpaque_SkAlphaType));
        bm.eraseColor(SK_ColorBLUE);
        for (const auto& rec : gRecs) {
            auto encoded = encode_ndk(bm.pixmap(), rec.format, rec.quality);
            if (!encoded) {
                ERRORF(r, "Failed to encode %s to %s\n", ToolUtils::colortype_name(ct), rec.name);
                continue;
            }
            auto gen = SkImageGenerators::MakeFromEncoded(std::move(encoded));
            if (!gen) {
                ERRORF(r, "Failed to decode from %s as %s\n", ToolUtils::colortype_name(ct),
                       rec.name);
                continue;
            }

            if (rec.name == kPng && bm.colorType() == kRGB_565_SkColorType) {
                REPORTER_ASSERT(r, gen->getInfo().colorType() == kRGB_565_SkColorType);
            } else {
                REPORTER_ASSERT(r, gen->getInfo().colorType() == kN32_SkColorType);
            }

            SkBitmap bm2;
            bm2.allocPixels(bm.info());
            REPORTER_ASSERT(r, gen->getPixels(bm2.pixmap()));

            for (int x = 0; x < bm.width();  x++)
            for (int y = 0; y < bm.height(); y++) {
                SkColor orig   = bm .getColor(x, y);
                SkColor actual = bm2.getColor(x, y);

                REPORTER_ASSERT(r, SkColorGetA(orig) == SkColorGetA(actual));
                REPORTER_ASSERT(r, SkColorGetA(orig) == 0xFF);

                if (rec.name == kPng || rec.name == kWebpLossless) {
                    REPORTER_ASSERT(r, orig == actual);
                } else {
                    int diffR = std::abs((int) SkColorGetR(orig) - (int) SkColorGetR(actual));
                    int diffG = std::abs((int) SkColorGetG(orig) - (int) SkColorGetG(actual));
                    int diffB = std::abs((int) SkColorGetB(orig) - (int) SkColorGetB(actual));
                    REPORTER_ASSERT(r, diffR <= 2 && diffG <= 1 && diffB <= 1);
                }
            }
        }
    }
}

DEF_TEST(NdkEncode_unsupportedFormats, r) {
    for (auto ct : { kRGBA_8888_SkColorType,
                     kRGB_565_SkColorType,
                     kRGBA_F16_SkColorType }) {
        SkBitmap bm;
        bm.allocPixels(SkImageInfo::Make(10, 10, ct, kOpaque_SkAlphaType));
        bm.eraseColor(SK_ColorBLUE);
        for (auto format : { SkEncodedImageFormat::kBMP,
                             SkEncodedImageFormat::kGIF,
                             SkEncodedImageFormat::kICO,
                             SkEncodedImageFormat::kWBMP,
                             SkEncodedImageFormat::kPKM,
                             SkEncodedImageFormat::kKTX,
                             SkEncodedImageFormat::kASTC,
                             SkEncodedImageFormat::kDNG,
                             SkEncodedImageFormat::kHEIF }) {
            REPORTER_ASSERT(r, !encode_ndk(bm.pixmap(), format, 100));
        }
    }
}

DEF_TEST(NdkEncode_badQuality, r) {
    for (auto ct : { kRGBA_8888_SkColorType,
                     kRGB_565_SkColorType,
                     kRGBA_F16_SkColorType }) {
        SkBitmap bm;
        bm.allocPixels(SkImageInfo::Make(10, 10, ct, kOpaque_SkAlphaType));
        bm.eraseColor(SK_ColorBLUE);
        for (auto format : { SkEncodedImageFormat::kJPEG,
                             SkEncodedImageFormat::kPNG,
                             SkEncodedImageFormat::kWEBP }) {
            for (int quality : {-1, -100, 101, 200}) {
                REPORTER_ASSERT(r, !encode_ndk(bm.pixmap(), format, quality));
            }
        }
    }
}

DEF_TEST(NdkEncode_nullPixels, r) {
    for (auto info : { SkImageInfo::MakeUnknown(),
                       SkImageInfo::MakeN32Premul(10, 10),
                       SkImageInfo::MakeN32Premul(0, 0)}) {
        SkPixmap pm(info, nullptr, info.minRowBytes());
        for (const auto& rec : gRecs) {
            REPORTER_ASSERT(r, !encode_ndk(pm, rec.format, rec.quality));
        }
    }
}

DEF_TEST(NdkEncode_badInfo, r) {
    // Allocate an arbitrary amount of memory. These infos don't have a natural
    // amount to allocate, and the encoder shouldn't touch the memory anyway.
    // But this allows us to verify that the bad info fails, even when the pixel
    // pointer is not null.
    void* pixels = sk_malloc_throw(1024);
    std::vector<SkPixmap> pixmaps{ SkPixmap(SkImageInfo::MakeN32Premul(-10, 10), pixels, 1000),
                                   SkPixmap(SkImageInfo::MakeN32Premul(10, -10), pixels, 200),
                                   SkPixmap(SkImageInfo::MakeN32Premul(10,  10), pixels, 20),
                                   SkPixmap(SkImageInfo::MakeN32Premul(10,  10), pixels, 41),
                                   SkPixmap(SkImageInfo::MakeN32Premul(10,  10), pixels, 0),
                                   SkPixmap(SkImageInfo::MakeN32Premul( 0,   0), pixels, 40)};
    if (sizeof(size_t) > sizeof(uint32_t)) {
        pixmaps.emplace_back(SkImageInfo::MakeN32Premul(10, 10),  pixels,
                             static_cast<size_t>(UINT32_MAX) + 1);
    }
    for (const auto& pm : pixmaps) {
        for (const auto& rec : gRecs) {
            REPORTER_ASSERT(r, !encode_ndk(pm, rec.format, rec.quality));
        }
    }
    free(pixels);
}

DEF_TEST(NdkEncode_unsupportedColorTypes, r) {
    for (SkColorType ct : {
        kUnknown_SkColorType,
        kAlpha_8_SkColorType,
        kARGB_4444_SkColorType,
        kRGB_888x_SkColorType,
        kBGRA_8888_SkColorType,
        kRGBA_1010102_SkColorType,
        kBGRA_1010102_SkColorType,
        kRGB_101010x_SkColorType,
        kBGR_101010x_SkColorType,
        kGray_8_SkColorType,
        kRGBA_F16Norm_SkColorType,
        kRGB_F16F16F16x_SkColorType,
        kRGBA_F32_SkColorType,
        kR8G8_unorm_SkColorType,
        kA16_float_SkColorType,
        kR16G16_float_SkColorType,
        kA16_unorm_SkColorType,
        kR16G16_unorm_SkColorType,
        kR16G16B16A16_unorm_SkColorType,
    }) {
        auto info = SkImageInfo::Make(7, 13, ct, kOpaque_SkAlphaType, SkColorSpace::MakeSRGB());
        SkBitmap bm;
        bm.allocPixels(info);
        bm.eraseColor(SK_ColorGREEN);
        for (const auto& rec : gRecs) {
            REPORTER_ASSERT(r, !encode_ndk(bm.pixmap(), rec.format, rec.quality));
        }
        if (!SkColorTypeIsAlwaysOpaque(ct)) {
            for (auto at : { kPremul_SkAlphaType, kUnpremul_SkAlphaType}) {
                info = info.makeAlphaType(at);
                bm.allocPixels(info);
                bm.eraseARGB(0x7F, 0xFF, 0xFF, 0xFF);
            }
            for (const auto& rec : gRecs) {
                REPORTER_ASSERT(r, !encode_ndk(bm.pixmap(), rec.format, rec.quality));
            }
        }
    }
}

DEF_TEST(NdkEncode_unsupportedAlphaTypes, r) {
    for (auto ct : { kRGBA_8888_SkColorType,
                     kRGB_565_SkColorType,
                     kRGBA_F16_SkColorType }) {
        for (auto at : { kUnknown_SkAlphaType, (SkAlphaType) -1}) {
            auto info = SkImageInfo::Make(10, 10, ct, at);
            size_t rowBytes = info.minRowBytes();
            void* pixels = sk_malloc_throw(info.computeByteSize(rowBytes));
            SkPixmap pm(info, pixels, rowBytes);
            for (const auto& rec : gRecs) {
                REPORTER_ASSERT(r, !encode_ndk(pm, rec.format, rec.quality));
            }
            free(pixels);
        }
    }
}

static constexpr skcms_TransferFunction k2Dot6 = {2.6f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};

static constexpr skcms_Matrix3x3 kDCIP3 = {{
        {0.486143, 0.323835, 0.154234},
        {0.226676, 0.710327, 0.0629966},
        {0.000800549, 0.0432385, 0.78275},
}};


static bool nearly_equal(float a, float b) {
    return fabs(a - b) < .002f;
}

static bool nearly_equal(const skcms_TransferFunction& x, const skcms_TransferFunction& y) {
    return nearly_equal(x.g, y.g)
        && nearly_equal(x.a, y.a)
        && nearly_equal(x.b, y.b)
        && nearly_equal(x.c, y.c)
        && nearly_equal(x.d, y.d)
        && nearly_equal(x.e, y.e)
        && nearly_equal(x.f, y.f);
}

static bool nearly_equal(const skcms_Matrix3x3& a, const skcms_Matrix3x3& b) {
    for (int i = 0; i < 3; i++)
    for (int j = 0; j < 3; j++) {
        if (!nearly_equal(a.vals[i][j], b.vals[i][j])) return false;
    }
    return true;
}

static bool nearly_equal(SkColorSpace* a, SkColorSpace* b) {
    skcms_TransferFunction fnA,     fnB;
    skcms_Matrix3x3        gamutA,  gamutB;
    return a && b && a->isNumericalTransferFn(&fnA) && a->toXYZD50(&gamutA)
                  && b->isNumericalTransferFn(&fnB) && b->toXYZD50(&gamutB)
             && nearly_equal(fnA, fnB) && nearly_equal(gamutA, gamutB);
}

DEF_TEST(NdkEncode_ColorSpace, r) {
    const struct {
        sk_sp<SkColorSpace> cs;
        const char*         name;
    } colorSpaces[] = {
        { sk_sp<SkColorSpace>(nullptr),                                                 "null"    },
        { SkColorSpace::MakeSRGB(),                                                     "srgb"    },
        { SkColorSpace::MakeSRGBLinear(),                                            "srgb-linear"},
        { SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kSRGB),      "bt709"   },
        { SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, SkNamedGamut::kRec2020),   "rec2020" },
        { SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,    SkNamedGamut::kDisplayP3), "p3"      },
        { SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2,   SkNamedGamut::kAdobeRGB),  "adobeRGB"},
        { SkColorSpace::MakeRGB(k2Dot6,                      kDCIP3),                   "dci-p3"  },
    };
    for (const auto& colorSpace : colorSpaces) {
        for (auto ct : { kRGBA_8888_SkColorType, kRGB_565_SkColorType, kRGBA_F16_SkColorType }) {
            SkBitmap bm;
            bm.allocPixels(SkImageInfo::Make(10, 10, ct, kOpaque_SkAlphaType, colorSpace.cs));
            bm.eraseColor(SK_ColorRED);

            for (const auto& rec : gRecs) {
                auto encoded = encode_ndk(bm.pixmap(), rec.format, rec.quality);
                REPORTER_ASSERT(r, encoded);
                auto gen = SkImageGenerators::MakeFromEncoded(std::move(encoded));
                REPORTER_ASSERT(r, gen);

                auto  expected = colorSpace.cs ? colorSpace.cs : SkColorSpace::MakeSRGB();
                auto* actual   = gen->getInfo().colorSpace();
                if (!nearly_equal(actual, expected.get())) {
                    const char* name = "unknown";
                    for (auto named : colorSpaces) {
                        if (nearly_equal(actual, named.cs.get())) {
                            name = named.name;
                            break;
                        }
                    }

                    ERRORF(r, "Mismatch: expected: %s\tactual:%s", colorSpace.name, name);
                }
            }
        }
    }
}

DEF_TEST(NdkEncode_unsupportedColorSpace, r) {
    std::vector<sk_sp<SkColorSpace>> unsupportedCs;
    for (auto gamut : { SkNamedGamut::kSRGB, SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
                        SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut));
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut));
        unsupportedCs.push_back(SkColorSpace::MakeRGB(k2Dot6, gamut));
    }

    for (auto gamut : { SkNamedGamut::kSRGB, SkNamedGamut::kDisplayP3,
                        SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, gamut));
    }

    for (auto gamut : { SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
                        SkNamedGamut::kXYZ }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kRec2020, gamut));
    }

    for (auto gamut : { SkNamedGamut::kAdobeRGB, SkNamedGamut::kDisplayP3,
                        SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut));
    }

    for (auto gamut : { SkNamedGamut::kAdobeRGB,
                        SkNamedGamut::kRec2020, SkNamedGamut::kXYZ }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut));
    }

    for (auto fn : { SkNamedTransferFn::kSRGB, SkNamedTransferFn::k2Dot2,
                     SkNamedTransferFn::kLinear, SkNamedTransferFn::kRec2020 }) {
        unsupportedCs.push_back(SkColorSpace::MakeRGB(fn, kDCIP3));
    }

    for (auto unsupported : unsupportedCs) {
        for (auto ct : { kRGBA_8888_SkColorType, kRGB_565_SkColorType, kRGBA_F16_SkColorType }) {
            SkBitmap bm;
            bm.allocPixels(SkImageInfo::Make(10, 10, ct, kOpaque_SkAlphaType, unsupported));
            bm.eraseColor(SK_ColorBLUE);

            for (const auto& rec : gRecs) {
                REPORTER_ASSERT(r, !encode_ndk(bm.pixmap(), rec.format, rec.quality));
            }
        }
    }
}

#endif // SK_ENABLE_NDK_IMAGES
