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

#include "src/codec/SkJpegxlCodec.h"

#include "include/codec/SkCodec.h"
#include "include/codec/SkJpegxlDecoder.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "include/private/SkEncodedInfo.h"
#include "include/private/SkTFitsIn.h"
#include "include/private/SkTemplates.h"
#include "include/private/SkTo.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkFrameHolder.h"
#include "src/core/SkColorData.h"
#include "src/core/SkStreamPriv.h"
#include "src/core/SkSwizzlePriv.h"

#include "jxl/codestream_header.h"  // NO_G3_REWRITE
#include "jxl/decode.h"  // NO_G3_REWRITE
#include "jxl/decode_cxx.h"  // NO_G3_REWRITE
#include "jxl/types.h"  // NO_G3_REWRITE

#include <cstdint>
#include <cstring>
#include <limits>
#include <utility>
#include <vector>

namespace {

class Frame : public SkFrame {
public:
    explicit Frame(int i, SkEncodedInfo::Alpha alpha) : INHERITED(i), fReportedAlpha(alpha) {}
    SkEncodedInfo::Alpha onReportedAlpha() const override { return fReportedAlpha; }

private:
    const SkEncodedInfo::Alpha fReportedAlpha;

    using INHERITED = SkFrame;
};

}  // namespace

bool SkJpegxlCodec::IsJpegxl(const void* buffer, size_t bytesRead) {
    JxlSignature result = JxlSignatureCheck(reinterpret_cast<const uint8_t*>(buffer), bytesRead);
    return (result == JXL_SIG_CODESTREAM) || (result == JXL_SIG_CONTAINER);
}

class SkJpegxlCodecPriv : public SkFrameHolder {
public:
    SkJpegxlCodecPriv() : fDecoder(JxlDecoderMake(/* memory_manager= */ nullptr)) {}
    JxlDecoderPtr fDecoder;  // unique_ptr with custom destructor
    JxlBasicInfo fInfo;
    bool fSeenAllFrames = false;
    std::vector<Frame> fFrames;
    int fLastProcessedFrame = SkCodec::kNoFrame;
    void* fDst = nullptr;
    size_t fPixelShift = 0;
    size_t fRowBytes = 0;
    SkColorType fDstColorType;

protected:
    const SkFrame* onGetFrame(int i) const override {
        SkASSERT(i >= 0 && static_cast<size_t>(i) < fFrames.size());
        return static_cast<const SkFrame*>(&fFrames[i]);
    }
};

SkJpegxlCodec::SkJpegxlCodec(std::unique_ptr<SkJpegxlCodecPriv> codec,
                             SkEncodedInfo&& info,
                             std::unique_ptr<SkStream> stream,
                             sk_sp<const SkData> data)
        : INHERITED(std::move(info), skcms_PixelFormat_RGBA_hhhh, std::move(stream))
        , fCodec(std::move(codec))
        , fData(std::move(data)) {}

std::unique_ptr<SkCodec> SkJpegxlCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
                                                       Result* result) {
    SkASSERT(result);
    if (!stream) {
        *result = SkCodec::kInvalidInput;
        return nullptr;
    }
    *result = kInternalError;
    // Either wrap or copy stream data.
    sk_sp<const SkData> data = nullptr;
    if (stream->getMemoryBase()) {
        data = SkData::MakeWithoutCopy(stream->getMemoryBase(), stream->getLength());
    } else {
        data = SkStreamPriv::CopyStreamToData(stream.get());
        // Data is copied; stream can be released now.
        stream.reset(nullptr);
    }

    auto priv = std::make_unique<SkJpegxlCodecPriv>();
    JxlDecoder* dec = priv->fDecoder.get();

    auto status = JxlDecoderSetUnpremultiplyAlpha(dec, JXL_TRUE);
    if (status != JXL_DEC_SUCCESS) {
        SkDEBUGFAIL("libjxl returned unexpected status");
        return nullptr;
    }

    // Only query metadata this time.
    status = JxlDecoderSubscribeEvents(dec, JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING);
    if (status != JXL_DEC_SUCCESS) {
        // Fresh instance must accept request for subscription.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return nullptr;
    }

    status = JxlDecoderSetInput(dec, data->bytes(), data->size());
    if (status != JXL_DEC_SUCCESS) {
        // Fresh instance must accept first chunk of input.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return nullptr;
    }

    status = JxlDecoderProcessInput(dec);
    if (status == JXL_DEC_NEED_MORE_INPUT) {
        *result = kIncompleteInput;
        return nullptr;
    }
    if (status != JXL_DEC_BASIC_INFO) {
        *result = kInvalidInput;
        return nullptr;
    }
    JxlBasicInfo& info = priv->fInfo;
    status = JxlDecoderGetBasicInfo(dec, &info);
    if (status != JXL_DEC_SUCCESS) {
        // Current event is "JXL_DEC_BASIC_INFO" -> can't fail.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return nullptr;
    }

    // Check that image dimensions are not too large.
    if (!SkTFitsIn<int32_t>(info.xsize) || !SkTFitsIn<int32_t>(info.ysize)) {
        *result = kInvalidInput;
        return nullptr;
    }
    int32_t width = SkTo<int32_t>(info.xsize);
    int32_t height = SkTo<int32_t>(info.ysize);

    bool hasAlpha = (info.alpha_bits != 0);
    bool isGray = (info.num_color_channels == 1);
    SkEncodedInfo::Alpha alpha =
            hasAlpha ? SkEncodedInfo::kUnpremul_Alpha : SkEncodedInfo::kOpaque_Alpha;
    SkEncodedInfo::Color color;
    if (hasAlpha) {
        color = isGray ? SkEncodedInfo::kGrayAlpha_Color : SkEncodedInfo::kRGBA_Color;
    } else {
        color = isGray ? SkEncodedInfo::kGray_Color : SkEncodedInfo::kRGB_Color;
    }

    status = JxlDecoderProcessInput(dec);
    if (status != JXL_DEC_COLOR_ENCODING) {
        *result = kInvalidInput;
        return nullptr;
    }

    size_t iccSize = 0;
    // TODO(eustas): format field is currently ignored by decoder.
    status = JxlDecoderGetICCProfileSize(dec, JXL_COLOR_PROFILE_TARGET_DATA, &iccSize);
    if (status != JXL_DEC_SUCCESS) {
        // Likely incompatible colorspace.
        iccSize = 0;
    }
    std::unique_ptr<SkCodecs::ColorProfile> profile;
    if (iccSize) {
        auto icc = SkData::MakeUninitialized(iccSize);
        status = JxlDecoderGetColorAsICCProfile(dec,
                                                JXL_COLOR_PROFILE_TARGET_DATA,
                                                reinterpret_cast<uint8_t*>(icc->writable_data()),
                                                iccSize);
        if (status != JXL_DEC_SUCCESS) {
            // Current event is JXL_DEC_COLOR_ENCODING -> can't fail.
            SkDEBUGFAIL("libjxl returned unexpected status");
            return nullptr;
        }
        profile = SkCodecs::ColorProfile::MakeICCProfile(std::move(icc));
    }

    const int bitsPerComponent = info.bits_per_sample > 8 ? 16 : 8;

    *result = kSuccess;
    SkEncodedInfo encodedInfo = SkEncodedInfo::Make(
            width, height, color, alpha, bitsPerComponent, std::move(profile), info.bits_per_sample);

    return std::unique_ptr<SkCodec>(new SkJpegxlCodec(
            std::move(priv), std::move(encodedInfo), std::move(stream), std::move(data)));
}

SkCodec::Result SkJpegxlCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
                                           const Options& options, int* rowsDecodedPtr) {
    // TODO(eustas): implement
    if (options.fSubset) {
        return kUnimplemented;
    }
    if (dstInfo.dimensions() != this->dimensions()) {
        return kInvalidScale;
    }
    auto& codec = *fCodec.get();
    const int index = options.fFrameIndex;
    SkASSERT(0 == index || static_cast<size_t>(index) < codec.fFrames.size());
    auto* dec = codec.fDecoder.get();
    JxlDecoderStatus status;

    if ((codec.fLastProcessedFrame >= index) || (codec.fLastProcessedFrame == SkCodec::kNoFrame)) {
        codec.fLastProcessedFrame = SkCodec::kNoFrame;
        JxlDecoderRewind(dec);
        status = JxlDecoderSubscribeEvents(dec, JXL_DEC_FRAME | JXL_DEC_FULL_IMAGE);
        if (status != JXL_DEC_SUCCESS) {
            // Fresh decoder instance (after rewind) must accept subscription request.
            SkDEBUGFAIL("libjxl returned unexpected status");
            return kInternalError;
        }
        status = JxlDecoderSetInput(dec, fData->bytes(), fData->size());
        if (status != JXL_DEC_SUCCESS) {
            // Fresh decoder instance (after rewind) must accept first data chunk.
            SkDEBUGFAIL("libjxl returned unexpected status");
            return kInternalError;
        }
        SkASSERT(codec.fLastProcessedFrame + 1 == 0);
    }

    int nextFrame = codec.fLastProcessedFrame + 1;
    if (nextFrame < index) {
        JxlDecoderSkipFrames(dec, index - nextFrame);
    }

    // Decode till the frame start.
    status = JxlDecoderProcessInput(dec);
    // TODO(eustas): actually, frame is not completely processed; for streaming / partial decoding
    //               we should also add a flag that "last processed frame" is still incomplete, and
    //               flip that flag when frame decoding is over.
    codec.fLastProcessedFrame = index;
    if (status != JXL_DEC_FRAME) {
        // TODO(eustas): check status: it might be either corrupted or incomplete input.
        return kInternalError;
    }

    codec.fDst = dst;
    codec.fRowBytes = rowBytes;
    codec.fPixelShift = dstInfo.shiftPerPixel();
    codec.fDstColorType = dstInfo.colorType();

    // TODO(eustas): consider grayscale.
    uint32_t numColorChannels = 3;
    // TODO(eustas): consider no-alpha.
    uint32_t numAlphaChannels = 1;
    // NB: SKIA works with little-endian F16s.
    auto endianness = JXL_LITTLE_ENDIAN;

    // Internally JXL does most processing in floats. By "default" we request
    // output data type to be U8; it takes less memory, but results in some precision loss.
    //  We request F16 in two cases:
    //  - destination type is F16
    //  - color transformation is required; in this case values are remapped,
    //    and with 8-bit precision it is likely that visual artefact will appear
    //    (like banding, etc.)
    bool halfFloatOutput = false;
    if (fCodec->fDstColorType == kRGBA_F16_SkColorType) halfFloatOutput = true;
    if (colorXform()) halfFloatOutput = true;
    auto dataType = halfFloatOutput ? JXL_TYPE_FLOAT16 : JXL_TYPE_UINT8;

    JxlPixelFormat format =
        {numColorChannels + numAlphaChannels, dataType, endianness, /* align = */ 0};
    status = JxlDecoderSetImageOutCallback(dec, &format, SkJpegxlCodec::imageOutCallback, this);
    if (status != JXL_DEC_SUCCESS) {
        // Current event is JXL_DEC_FRAME -> decoder must accept callback.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return kInternalError;
    }

    // Decode till the frame start.
    status = JxlDecoderProcessInput(dec);
    if (status != JXL_DEC_FULL_IMAGE) {
        // TODO(eustas): check status: it might be either corrupted or incomplete input.
        return kInternalError;
    }
    // TODO(eustas): currently it is supposed that complete input is accessible;
    //               when streaming support is added JXL_DEC_NEED_MORE_INPUT would also
    //               become a legal outcome; amount of decoded scanlines should be calculated
    //               based on callback invocations / render-pipeline API.
    *rowsDecodedPtr = dstInfo.height();

    return kSuccess;
}

bool SkJpegxlCodec::onRewind() {
    if (!this->rewindStream()) {
        return false;
    }
    JxlDecoderRewind(fCodec->fDecoder.get());
    return true;
}

bool SkJpegxlCodec::conversionSupported(const SkImageInfo& dstInfo, bool srcIsOpaque,
                                        bool needsColorXform) {
    if (!SkCodecPriv::ValidAlpha(dstInfo.alphaType(), srcIsOpaque)) {
        return false;
    }
    fCodec->fDstColorType = dstInfo.colorType();
    switch (dstInfo.colorType()) {
        case kRGBA_8888_SkColorType:
            return true;  // memcpy or RGBA_to_rgbA
        case kBGRA_8888_SkColorType:
            return true;  // RGBA_to_BGRA or RGBA_to_bgrA
        case kRGBA_1010102_SkColorType:
            return true;

        case kRGBA_F16_SkColorType:
            return true;  // memcpy

        case kRGB_565_SkColorType:
            return srcIsOpaque;

        case kGray_8_SkColorType:
            return this->getEncodedInfo().color() == SkEncodedInfo::kGray_Color;
        case kAlpha_8_SkColorType:
            return this->getEncodedInfo().color() == SkEncodedInfo::kGray_Color && !needsColorXform;

        default:
            return false;
    }
    return true;
}

void SkJpegxlCodec::imageOutCallback(void* opaque, size_t x, size_t y,
                                     size_t num_pixels, const void* pixels) {
    SkJpegxlCodec* instance = reinterpret_cast<SkJpegxlCodec*>(opaque);
    auto& codec = *instance->fCodec.get();
    if (y >= (size_t)instance->dimensions().height() ||
        x >= (size_t)instance->dimensions().width()) {
        return;
    }
    if (num_pixels > (size_t)instance->dimensions().width() - x) {
        num_pixels = instance->dimensions().width() - x;
    }
    size_t offset = y * codec.fRowBytes + (x << codec.fPixelShift);
    void* dst = SkTAddOffset<void>(codec.fDst, offset);
    if (instance->colorXform()) {
        instance->applyColorXform(dst, pixels, num_pixels);
        return;
    }
    const bool premul = !instance->getEncodedInfo().opaque() &&
                        instance->dstInfo().alphaType() == kPremul_SkAlphaType;
    switch (codec.fDstColorType) {
        case kRGBA_8888_SkColorType:
            if (premul) {
                SkOpts::RGBA_to_rgbA(reinterpret_cast<uint32_t*>(dst),
                                     reinterpret_cast<const uint32_t*>(pixels),
                                     num_pixels);
            } else {
                memcpy(dst, pixels, 4 * num_pixels);
            }
            return;
        case kBGRA_8888_SkColorType:
            if (premul) {
                SkOpts::RGBA_to_bgrA(reinterpret_cast<uint32_t*>(dst),
                                     reinterpret_cast<const uint32_t*>(pixels),
                                     num_pixels);
            } else {
                SkOpts::RGBA_to_BGRA(reinterpret_cast<uint32_t*>(dst),
                                     reinterpret_cast<const uint32_t*>(pixels),
                                     num_pixels);
            }
            return;
        case kRGBA_F16_SkColorType:
            memcpy(dst, pixels, 8 * num_pixels);
            return;
        case kRGB_565_SkColorType: {
            const uint8_t* src = reinterpret_cast<const uint8_t*>(pixels);
            uint16_t* dst16 = reinterpret_cast<uint16_t*>(dst);
            for (size_t i = 0; i < num_pixels; ++i) {
                dst16[i] = SkPack888ToRGB16(src[4 * i + 0], src[4 * i + 1], src[4 * i + 2]);
            }
            return;
        }
        case kGray_8_SkColorType:
        case kAlpha_8_SkColorType: {
            const uint8_t* src = reinterpret_cast<const uint8_t*>(pixels);
            uint8_t* dst8 = reinterpret_cast<uint8_t*>(dst);
            for (size_t i = 0; i < num_pixels; ++i) {
                dst8[i] = src[4 * i + 0];
            }
            return;
        }
        default:
            SK_ABORT("Selected output format is not supported yet");
            return;
    }
}

bool SkJpegxlCodec::scanFrames() {
    auto decoder = JxlDecoderMake(/* memory_manager = */ nullptr);
    JxlDecoder* dec = decoder.get();
    auto* frameHolder = fCodec.get();
    auto& frames = frameHolder->fFrames;
    const auto& info = fCodec->fInfo;
    frames.clear();

    auto alpha = (info.alpha_bits != 0) ? SkEncodedInfo::Alpha::kUnpremul_Alpha
                                        : SkEncodedInfo::Alpha::kOpaque_Alpha;

    auto status = JxlDecoderSubscribeEvents(dec, JXL_DEC_FRAME);
    if (status != JXL_DEC_SUCCESS) {
        // Fresh instance must accept request for subscription.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return true;
    }

    status = JxlDecoderSetInput(dec, fData->bytes(), fData->size());
    if (status != JXL_DEC_SUCCESS) {
        // Fresh instance must accept first input chunk.
        SkDEBUGFAIL("libjxl returned unexpected status");
        return true;
    }

    while (true) {
        status = JxlDecoderProcessInput(dec);
        switch (status) {
            case JXL_DEC_FRAME: {
                size_t frameId = frames.size();
                JxlFrameHeader frameHeader;
                if (JxlDecoderGetFrameHeader(dec, &frameHeader) != JXL_DEC_SUCCESS) {
                    return true;
                }
                frames.emplace_back(static_cast<int>(frameId), alpha);
                auto& frame = frames.back();
                // TODO(eustas): for better consistency we need to track total duration and report
                //               frame duration as delta to previous frame.
                int duration = (1000 * frameHeader.duration * info.animation.tps_denominator) /
                               info.animation.tps_numerator;
                frame.setDuration(duration);
                frameHolder->setAlphaAndRequiredFrame(&frame);
                break;
            }
            case JXL_DEC_SUCCESS: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
}

int SkJpegxlCodec::onGetFrameCount() {
    if (!fCodec->fInfo.have_animation) {
        return 1;
    }

    if (!fCodec->fSeenAllFrames) {
        fCodec->fSeenAllFrames = scanFrames();
    }

    return fCodec->fFrames.size();
}

bool SkJpegxlCodec::onGetFrameInfo(int index, FrameInfo* frameInfo) const {
    if (index < 0) {
        return false;
    }
    if (static_cast<size_t>(index) >= fCodec->fFrames.size()) {
        return false;
    }
    fCodec->fFrames[index].fillIn(frameInfo, true);
    return true;
}

int SkJpegxlCodec::onGetRepetitionCount() {
    JxlBasicInfo& info = fCodec->fInfo;
    if (!info.have_animation) {
        return 0;
    }

    if (info.animation.num_loops == 0) {
        return kRepetitionCountInfinite;
    }

    if (SkTFitsIn<int>(info.animation.num_loops)) {
        return info.animation.num_loops - 1;
    }

    // Largest "non-infinite" value.
    return std::numeric_limits<int>::max();
}

SkCodec::IsAnimated SkJpegxlCodec::onIsAnimated() {
    JxlBasicInfo& info = fCodec->fInfo;
    return info.have_animation ? IsAnimated::kYes : IsAnimated::kNo;
}

const SkFrameHolder* SkJpegxlCodec::getFrameHolder() const {
    return fCodec.get();
}

// TODO(eustas): implement
// SkCodec::Result SkJpegxlCodec::onStartScanlineDecode(
//     const SkImageInfo& /*dstInfo*/, const Options& /*options*/) { return kUnimplemented; }

// TODO(eustas): implement
// SkCodec::Result SkJpegxlCodec::onStartIncrementalDecode(
//     const SkImageInfo& /*dstInfo*/, void*, size_t, const Options&) { return kUnimplemented; }

// TODO(eustas): implement
// SkCodec::Result SkJpegxlCodec::onIncrementalDecode(int*) { return kUnimplemented; }

// TODO(eustas): implement
// bool SkJpegxlCodec::onSkipScanlines(int /*countLines*/) { return false; }

// TODO(eustas): implement
// int SkJpegxlCodec::onGetScanlines(
//     void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }

// TODO(eustas): implement
// SkSampler* SkJpegxlCodec::getSampler(bool /*createIfNecessary*/) { return nullptr; }

namespace SkJpegxlDecoder {
bool IsJpegxl(const void* data, size_t len) {
    return SkJpegxlCodec::IsJpegxl(data, len);
}

std::unique_ptr<SkCodec> Decode(std::unique_ptr<SkStream> stream,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    SkCodec::Result resultStorage;
    if (!outResult) {
        outResult = &resultStorage;
    }
    return SkJpegxlCodec::MakeFromStream(std::move(stream), outResult);
}

std::unique_ptr<SkCodec> Decode(sk_sp<const SkData> data,
                                SkCodec::Result* outResult,
                                SkCodecs::DecodeContext) {
    if (!data) {
        if (outResult) {
            *outResult = SkCodec::kInvalidInput;
        }
        return nullptr;
    }
    return Decode(SkMemoryStream::Make(std::move(data)), outResult, nullptr);
}
}  // namespace SkJpegDecoder
