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

#include "src/codec/SkJpegGainmap.h"

#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/private/SkGainmapInfo.h"
#include "include/private/base/SkFloatingPoint.h"
#include "include/utils/SkParse.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkJpegMultiPicture.h"
#include "src/codec/SkJpegPriv.h"
#include "src/codec/SkJpegSegmentScan.h"
#include "src/xml/SkDOM.h"

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

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkStream helpers.

/*
 * Class that will will rewind an SkStream, and then restore it to its original position when it
 * goes out of scope. If the SkStream is not seekable, then the stream will not be altered at all,
 * and will return false from canRestore.
 */

class ScopedSkStreamRestorer {
public:
    ScopedSkStreamRestorer(SkStream* stream)
            : fStream(stream), fPosition(stream->hasPosition() ? stream->getPosition() : 0) {
        if (canRestore()) {
            if (!fStream->rewind()) {
                SkCodecPrintf("Failed to rewind decoder stream.\n");
            }
        }
    }
    ~ScopedSkStreamRestorer() {
        if (canRestore()) {
            if (!fStream->seek(fPosition)) {
                SkCodecPrintf("Failed to restore decoder stream.\n");
            }
        }
    }
    bool canRestore() const { return fStream->hasPosition(); }

private:
    SkStream* const fStream;
    const size_t fPosition;
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// SkDOM and XMP helpers.

/*
 * Build an SkDOM from an SkData. Return true on success and false on failure (including the input
 * data being nullptr).
 */
bool SkDataToSkDOM(sk_sp<const SkData> data, SkDOM* dom) {
    if (!data) {
        return false;
    }
    auto stream = SkMemoryStream::MakeDirect(data->data(), data->size());
    if (!stream) {
        return false;
    }
    return dom->build(*stream) != nullptr;
}

/*
 * Given an SkDOM, verify that the dom is XMP, and find the first rdf:Description node that matches
 * the specified namespaces to the specified URIs. The XML structure that this function matches is
 * as follows (with NAMESPACEi and URIi being the parameters specified to this function):
 *
 *   <x:xmpmeta ...>
 *     <rdf:RDF ...>
 *       <rdf:Description NAMESPACE0="URI0" NAMESPACE1="URI1" .../>
 *     </rdf:RDF>
 *   </x:xmpmeta>
 */
const SkDOM::Node* FindXmpNamespaceUriMatch(const SkDOM& dom,
                                            const char* namespaces[],
                                            const char* uris[],
                                            size_t count) {
    const SkDOM::Node* root = dom.getRootNode();
    if (!root) {
        return nullptr;
    }
    const char* rootName = dom.getName(root);
    if (!rootName || strcmp(rootName, "x:xmpmeta") != 0) {
        return nullptr;
    }

    const char* kRdf = "rdf:RDF";
    for (const auto* rdf = dom.getFirstChild(root, kRdf); rdf;
         rdf = dom.getNextSibling(rdf, kRdf)) {
        const char* kDesc = "rdf:Description";
        for (const auto* desc = dom.getFirstChild(rdf, kDesc); desc;
             desc = dom.getNextSibling(desc, kDesc)) {
            bool allNamespaceURIsMatch = true;
            for (size_t i = 0; i < count; ++i) {
                if (!dom.hasAttr(desc, namespaces[i], uris[i])) {
                    allNamespaceURIsMatch = false;
                    break;
                }
            }
            if (allNamespaceURIsMatch) {
                return desc;
            }
        }
    }
    return nullptr;
}

/*
 * Given a node, see if that node has only one child with the indicated name. If so, see if that
 * child has only a single child of its own, and that child is text. If all of that is the case
 * then return the text, otherwise return nullptr.
 *
 * In the following example, innerText will be returned.
 *    <node><childName>innerText</childName></node>
 *
 * In the following examples, nullptr will be returned (because there are multiple children with
 * childName in the first case, and because the child has children of its own in the second).
 *    <node><childName>innerTextA</childName><childName>innerTextB</childName></node>
 *    <node><childName>innerText<otherGrandChild/></childName></node>
 */
static const char* GetUniqueChildText(const SkDOM& dom,
                                      const SkDOM::Node* node,
                                      const char* childName) {
    // Fail if there are multiple children with childName.
    if (dom.countChildren(node, childName) != 1) {
        return nullptr;
    }
    const auto* child = dom.getFirstChild(node, childName);
    if (!child) {
        return nullptr;
    }
    // Fail if the child has any children besides text.
    if (dom.countChildren(child) != 1) {
        return nullptr;
    }
    const auto* grandChild = dom.getFirstChild(child);
    if (dom.getType(grandChild) != SkDOM::kText_Type) {
        return nullptr;
    }
    // Return the text.
    return dom.getName(grandChild);
}

// Helper function that builds on GetUniqueChildText, returning true if the unique child with
// childName has inner text that matches an expected text.
static bool UniqueChildTextMatches(const SkDOM& dom,
                                   const SkDOM::Node* node,
                                   const char* childName,
                                   const char* expectedText) {
    const char* text = GetUniqueChildText(dom, node, childName);
    if (text && !strcmp(text, expectedText)) {
        return true;
    }
    return false;
}

// Helper function that builds on GetUniqueChildText, returning true if the unique child with
// childName has inner text that matches an expected integer.
static bool UniqueChildTextMatches(const SkDOM& dom,
                                   const SkDOM::Node* node,
                                   const char* childName,
                                   int32_t expectedValue) {
    const char* text = GetUniqueChildText(dom, node, childName);
    int32_t actualValue = 0;
    if (text && SkParse::FindS32(text, &actualValue)) {
        return actualValue == expectedValue;
    }
    return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Multi-PictureFormat Gainmap Functions

// Return true if the specified XMP metadata identifies this image as an HDR gainmap.
static bool XmpIsHDRGainMap(const sk_sp<const SkData>& xmpMetadata) {
    // Parse the XMP.
    SkDOM dom;
    if (!SkDataToSkDOM(xmpMetadata, &dom)) {
        return false;
    }

    // Find a node that matches the requested namespaces and URIs.
    const char* namespaces[2] = {"xmlns:apdi", "xmlns:HDRGainMap"};
    const char* uris[2] = {"http://ns.apple.com/pixeldatainfo/1.0/",
                           "http://ns.apple.com/HDRGainMap/1.0/"};
    const SkDOM::Node* node = FindXmpNamespaceUriMatch(dom, namespaces, uris, 2);
    if (!node) {
        return false;
    }
    if (!UniqueChildTextMatches(
                dom, node, "apdi:AuxiliaryImageType", "urn:com:apple:photo:2020:aux:hdrgainmap")) {
        SkCodecPrintf("Did not find auxiliary image type.\n");
        return false;
    }
    if (!UniqueChildTextMatches(dom, node, "HDRGainMap:HDRGainMapVersion", 65536)) {
        SkCodecPrintf("HDRGainMapVersion absent or not 65536.\n");
        return false;
    }

    // This node will often have StoredFormat and NativeFormat children that have inner text that
    // specifies the integer 'L008' (also known as kCVPixelFormatType_OneComponent8).
    return true;
}

bool SkJpegGetMultiPictureGainmap(sk_sp<const SkData> decoderMpfMetadata,
                                  SkStream* decoderStream,
                                  SkGainmapInfo* outInfo,
                                  std::unique_ptr<SkStream>* outGainmapImageStream) {
    // The decoder has already scanned for MPF metadata. If it doesn't exist, or it doesn't parse,
    // then early-out.
    if (!decoderMpfMetadata || !SkJpegParseMultiPicture(decoderMpfMetadata)) {
        return false;
    }

    // The implementation of Multi-Picture images requires a seekable stream. Save the position so
    // that it can be restored before returning.
    ScopedSkStreamRestorer streamRestorer(decoderStream);
    if (!streamRestorer.canRestore()) {
        SkCodecPrintf("Multi-Picture gainmap extraction requires a seekable stream.\n");
        return false;
    }

    // Scan the original decoder stream.
    auto scan = SkJpegSeekableScan::Create(decoderStream);
    if (!scan) {
        SkCodecPrintf("Failed to scan decoder stream.\n");
        return false;
    }

    // Extract the Multi-Picture image streams in the original decoder stream (we needed the scan to
    // find the offsets of the MP images within the original decoder stream).
    auto mpStreams = SkJpegExtractMultiPictureStreams(scan.get());
    if (!mpStreams) {
        SkCodecPrintf("Failed to extract MP image streams.\n");
        return false;
    }

    // Iterate over the MP image streams.
    for (auto& mpImage : mpStreams->images) {
        if (!mpImage.stream) {
            continue;
        }

        // Create a scan of this MP image.
        auto mpImageScan = SkJpegSeekableScan::Create(mpImage.stream.get());
        if (!mpImageScan) {
            SkCodecPrintf("Failed to can MP image.\n");
            continue;
        }

        // Search for the XMP metadata in the MP image's scan.
        for (const auto& segment : mpImageScan->segments()) {
            if (segment.marker != kXMPMarker) {
                continue;
            }
            auto xmpMetadata = mpImageScan->copyParameters(segment, kXMPSig, sizeof(kXMPSig));
            if (!xmpMetadata) {
                continue;
            }

            // If this XMP does not indicate that the image is an HDR gainmap, then continue.
            if (!XmpIsHDRGainMap(xmpMetadata)) {
                continue;
            }

            // This MP image is the gainmap image. Populate its stream and the rendering parameters
            // for its format.
            if (outGainmapImageStream) {
                if (!mpImage.stream->rewind()) {
                    SkCodecPrintf("Failed to rewind gainmap image stream.\n");
                    return false;
                }
                *outGainmapImageStream = std::move(mpImage.stream);
            }
            constexpr float kLogRatioMin = 0.f;
            constexpr float kLogRatioMax = 1.f;
            outInfo->fLogRatioMin = {kLogRatioMin, kLogRatioMin, kLogRatioMin, 1.f};
            outInfo->fLogRatioMax = {kLogRatioMax, kLogRatioMax, kLogRatioMax, 1.f};
            outInfo->fGainmapGamma = {1.f, 1.f, 1.f, 1.f};
            outInfo->fEpsilonSdr = 1 / 128.f;
            outInfo->fEpsilonHdr = 1 / 128.f;
            outInfo->fHdrRatioMin = 1.f;
            outInfo->fHdrRatioMax = sk_float_exp(kLogRatioMax);
            outInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kSDR;
            outInfo->fType = SkGainmapInfo::Type::kMultiPicture;
            return true;
        }
    }
    return false;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// JpegR Gainmap functions

static bool SkJpegGetJpegRGainmapParseXMP(sk_sp<const SkData> xmpMetadata,
                                          size_t* outOffset,
                                          size_t* outSize,
                                          SkGainmapInfo::Type* outType,
                                          float* outRangeScalingFactor) {
    // Parse the XMP.
    SkDOM dom;
    if (!SkDataToSkDOM(xmpMetadata, &dom)) {
        return false;
    }

    // Find a node that matches the requested namespaces and URIs.
    const char* namespaces[2] = {"xmlns:GContainer", "xmlns:RecoveryMap"};
    const char* uris[2] = {"http://ns.google.com/photos/1.0/container/",
                           "http://ns.google.com/photos/1.0/recoverymap/"};
    const SkDOM::Node* node = FindXmpNamespaceUriMatch(dom, namespaces, uris, 2);
    if (!node) {
        return false;
    }

    // The node must have a GContainer:Version child that specifies version 1.
    if (!UniqueChildTextMatches(dom, node, "GContainer:Version", 1)) {
        SkCodecPrintf("GContainer:Version is absent or not 1");
        return false;
    }

    // The node must have a GContainer:Directory.
    const auto* directory = dom.getFirstChild(node, "GContainer:Directory");
    if (!directory) {
        SkCodecPrintf("Missing GContainer:Directory");
        return false;
    }

    // That GContainer:Directory must have a sequence of  items.
    const auto* seq = dom.getFirstChild(directory, "rdf:Seq");
    if (!seq) {
        SkCodecPrintf("Missing rdf:Seq");
        return false;
    }

    // Iterate through the items in the GContainer:Directory's sequence. Keep a running sum of the
    // GContainer::ItemLength of all items that appear before the RecoveryMap.
    bool isFirstItem = true;
    size_t itemLengthSum = 0;
    for (const auto* li = dom.getFirstChild(seq, "rdf:li"); li;
         li = dom.getNextSibling(li, "rdf:li")) {
        // Each list item must contain a GContainer item.
        const auto* item = dom.getFirstChild(li, "GContainer:Item");
        if (!item) {
            SkCodecPrintf("List item does not have GContainer:Item.\n");
            return false;
        }
        // An ItemSemantic is required for every GContainer item.
        const char* itemSemantic = dom.findAttr(item, "GContainer:ItemSemantic");
        if (!itemSemantic) {
            SkCodecPrintf("GContainer item is missing ItemSemantic.\n");
            return false;
        }
        // An ItemMime is required for every GContainer item.
        const char* itemMime = dom.findAttr(item, "GContainer:ItemMime");
        if (!itemMime) {
            SkCodecPrintf("GContainer item is missing ItemMime.\n");
            return false;
        }
        if (isFirstItem) {
            isFirstItem = false;
            // The first item must be Primary.
            if (strcmp(itemSemantic, "Primary") != 0) {
                SkCodecPrintf("First item is not Primary.\n");
                return false;
            }
            // The first item has mime type image/jpeg (we are decoding a jpeg).
            if (strcmp(itemMime, "image/jpeg") != 0) {
                SkCodecPrintf("Primary does not report that it is image/jpeg.\n");
                return false;
            }
            // The Verison of 1 is required for the Primary.
            if (!dom.hasAttr(item, "RecoveryMap:Version", "1")) {
                SkCodecPrintf("RecoveryMap:Version is not 1.");
                return false;
            }
            // The TransferFunction is required for the Primary.
            int32_t transferFunction = 0;
            if (!dom.findS32(item, "RecoveryMap:TransferFunction", &transferFunction)) {
                SkCodecPrintf("RecoveryMap:TransferFunction is absent.");
                return false;
            }
            switch (transferFunction) {
                case 0:
                    *outType = SkGainmapInfo::Type::kJpegR_Linear;
                    break;
                case 1:
                    *outType = SkGainmapInfo::Type::kJpegR_HLG;
                    break;
                case 2:
                    *outType = SkGainmapInfo::Type::kJpegR_PQ;
                    break;
                default:
                    SkCodecPrintf("RecoveryMap:TransferFunction is out of range.");
                    return false;
            }
            // The RangeScalingFactor is required for the Primary.
            SkScalar rangeScalingFactor = 1.f;
            if (!dom.findScalars(item, "RecoveryMap:RangeScalingFactor", &rangeScalingFactor, 1)) {
                SkCodecPrintf("RecoveryMap:RangeScalingFactor is absent.");
                return false;
            }
            *outRangeScalingFactor = rangeScalingFactor;
        } else {
            // An ItemLength is required for all non-Primary GContainter items.
            int32_t itemLength = 0;
            if (!dom.findS32(item, "GContainer:ItemLength", &itemLength)) {
                SkCodecPrintf("GContainer:ItemLength is absent.");
                return false;
            }
            // If this is not the recovery map, then read past it.
            if (strcmp(itemSemantic, "RecoveryMap") != 0) {
                itemLengthSum += itemLength;
                continue;
            }
            // The recovery map must have mime type image/jpeg in this implementation.
            if (strcmp(itemMime, "image/jpeg") != 0) {
                SkCodecPrintf("RecoveryMap does not report that it is image/jpeg.\n");
                return false;
            }

            // This is the recovery map.
            *outOffset = itemLengthSum;
            *outSize = itemLength;
            return true;
        }
    }
    return false;
}

bool SkJpegGetJpegRGainmap(sk_sp<const SkData> xmpMetadata,
                           SkStream* decoderStream,
                           SkGainmapInfo* outInfo,
                           std::unique_ptr<SkStream>* outGainmapImageStream) {
    // Parse the XMP metadata of the original image, to see if it specifies a RecoveryMap.
    size_t itemOffsetFromEndOfImage = 0;
    size_t itemSize = 0;
    SkGainmapInfo::Type type = SkGainmapInfo::Type::kUnknown;
    float rangeScalingFactor = 1.f;
    if (!SkJpegGetJpegRGainmapParseXMP(
                xmpMetadata, &itemOffsetFromEndOfImage, &itemSize, &type, &rangeScalingFactor)) {
        return false;
    }

    // The implementation of GContainer images requires a seekable stream. Save the position so that
    // it can be restored before returning.
    ScopedSkStreamRestorer streamRestorer(decoderStream);
    if (!streamRestorer.canRestore()) {
        SkCodecPrintf("RecoveryMap gainmap extraction requires a seekable stream.\n");
        return false;
    }

    // The offset read from the XMP metadata is relative to the end of the EndOfImage marker in the
    // original decoder stream. Create a full scan of the original decoder stream, so we can find
    // that EndOfImage marker's offset in the decoder stream.
    auto scan = SkJpegSeekableScan::Create(decoderStream, SkJpegSegmentScanner::kMarkerEndOfImage);
    if (!scan) {
        SkCodecPrintf("Failed to do full scan.\n");
        return false;
    }
    const auto& lastSegment = scan->segments().back();
    const size_t endOfImageOffset = lastSegment.offset + SkJpegSegmentScanner::kMarkerCodeSize;
    const size_t itemOffsetFromStartOfImage = endOfImageOffset + itemOffsetFromEndOfImage;

    // Extract the gainmap image's stream.
    auto gainmapImageStream = scan->getSubsetStream(itemOffsetFromStartOfImage, itemSize);
    if (!gainmapImageStream) {
        SkCodecPrintf("Failed to extract gainmap stream.");
        return false;
    }

    // Populate the output parameters for this format.
    if (outGainmapImageStream) {
        if (!gainmapImageStream->rewind()) {
            SkCodecPrintf("Failed to rewind gainmap image stream.");
            return false;
        }
        *outGainmapImageStream = std::move(gainmapImageStream);
    }

    const float kLogRatioMax = sk_float_log(rangeScalingFactor);
    const float kLogRatioMin = -kLogRatioMax;
    outInfo->fLogRatioMin = {kLogRatioMin, kLogRatioMin, kLogRatioMin, 1.f};
    outInfo->fLogRatioMax = {kLogRatioMax, kLogRatioMax, kLogRatioMax, 1.f};
    outInfo->fGainmapGamma = {1.f, 1.f, 1.f, 1.f};
    outInfo->fEpsilonSdr = 0.f;
    outInfo->fEpsilonHdr = 0.f;
    outInfo->fHdrRatioMin = 1.f;
    outInfo->fHdrRatioMax = rangeScalingFactor;
    outInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kSDR;
    outInfo->fType = type;
    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// HDRGM support

// Helper function to read a 1 or 3 floats and write them into an SkColor4f.
static void find_per_channel_attr(const SkDOM& dom,
                                  const SkDOM::Node* node,
                                  const char* attr,
                                  SkColor4f* outColor) {
    SkScalar values[3] = {0.f, 0.f, 0.f};
    if (dom.findScalars(node, attr, values, 3)) {
        *outColor = {values[0], values[1], values[2], 1.f};
    } else if (dom.findScalars(node, attr, values, 1)) {
        *outColor = {values[0], values[0], values[0], 1.f};
    }
}

bool SkJpegGetHDRGMGainmapInfo(sk_sp<const SkData> xmpMetadata,
                               SkStream* decoderStream,
                               SkGainmapInfo* outGainmapInfo) {
    // Parse the XMP.
    SkDOM dom;
    if (!SkDataToSkDOM(xmpMetadata, &dom)) {
        return false;
    }

    // Find a node that matches the requested namespace and URI.
    const char* namespaces[1] = {"xmlns:hdrgm"};
    const char* uris[1] = {"http://ns.adobe.com/hdr-gain-map/1.0/"};
    const SkDOM::Node* node = FindXmpNamespaceUriMatch(dom, namespaces, uris, 1);
    if (!node) {
        return false;
    }

    // Initialize the parameters to their defaults.
    SkColor4f gainMapMin = {0.f, 0.f, 0.f, 1.f};
    SkColor4f gainMapMax = {1.f, 1.f, 1.f, 1.f};
    SkColor4f gamma = {0.f, 0.f, 0.f, 1.f};
    SkColor4f offsetSdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
    SkColor4f offsetHdr = {1.f / 64.f, 1.f / 64.f, 1.f / 64.f, 0.f};
    SkScalar hdrCapacityMin = 0.f;
    SkScalar hdrCapacityMax = 1.f;

    // Read all parameters that are present.
    const char* baseRendition = dom.findAttr(node, "hdrgm:BaseRendition");
    find_per_channel_attr(dom, node, "hdrgm:GainMapMin", &gainMapMin);
    find_per_channel_attr(dom, node, "hdrgm:GainMapMax", &gainMapMax);
    find_per_channel_attr(dom, node, "hdrgm:Gamma", &gamma);
    find_per_channel_attr(dom, node, "hdrgm:OffsetSDR", &offsetSdr);
    find_per_channel_attr(dom, node, "hdrgm:OffsetHDR", &offsetHdr);
    dom.findScalar(node, "hdrgm:HDRCapacityMin", &hdrCapacityMin);
    dom.findScalar(node, "hdrgm:HDRCapacityMax", &hdrCapacityMax);

    // Translate all parameters to SkGainmapInfo's expected format.
    // TODO(ccameron): Move all of SkGainmapInfo to linear space.
    const float kLog2 = sk_float_log(2.f);
    outGainmapInfo->fLogRatioMin = {
            gainMapMin.fR * kLog2, gainMapMin.fG * kLog2, gainMapMin.fB * kLog2, 1.f};
    outGainmapInfo->fLogRatioMax = {
            gainMapMax.fR * kLog2, gainMapMax.fG * kLog2, gainMapMax.fB * kLog2, 1.f};
    outGainmapInfo->fGainmapGamma = gamma;
    // TODO(ccameron): Use SkColor4f for epsilons.
    outGainmapInfo->fEpsilonSdr = (offsetSdr.fR + offsetSdr.fG + offsetSdr.fB) / 3.f;
    outGainmapInfo->fEpsilonHdr = (offsetHdr.fR + offsetHdr.fG + offsetHdr.fB) / 3.f;
    outGainmapInfo->fHdrRatioMin = sk_float_exp(hdrCapacityMin * kLog2);
    outGainmapInfo->fHdrRatioMax = sk_float_exp(hdrCapacityMax * kLog2);
    if (baseRendition && !strcmp(baseRendition, "HDR")) {
        outGainmapInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kHDR;
    } else {
        outGainmapInfo->fBaseImageType = SkGainmapInfo::BaseImageType::kSDR;
    }
    outGainmapInfo->fType = SkGainmapInfo::Type::kHDRGM;
    return true;
}
