/*
 * 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 "src/codec/SkCodecPriv.h"
#include "src/codec/SkJpegMultiPicture.h"
#include "src/codec/SkJpegPriv.h"
#include "src/codec/SkJpegSegmentScan.h"
#include "src/codec/SkJpegSourceMgr.h"
#include "src/codec/SkJpegXmp.h"

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

bool SkJpegGetMultiPictureGainmap(const SkJpegMultiPictureParameters* mpParams,
                                  SkJpegSourceMgr* decoderSource,
                                  SkGainmapInfo* outInfo,
                                  std::unique_ptr<SkStream>* outGainmapImageStream) {
    // 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(mpParams, decoderSource);
    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 temporary source manager for this MP image.
        auto mpImageSource = SkJpegSourceMgr::Make(mpImage.stream.get());

        // Collect the potential XMP segments.
        std::vector<sk_sp<SkData>> app1Params;
        for (const auto& segment : mpImageSource->getAllSegments()) {
            if (segment.marker != kXMPMarker) {
                continue;
            }
            auto parameters = mpImageSource->getSegmentParameters(segment);
            if (!parameters) {
                continue;
            }
            app1Params.push_back(std::move(parameters));
        }

        // Build XMP if possible.
        auto xmp = SkJpegXmp::Make(app1Params);
        if (!xmp) {
            continue;
        }

        // Check if this is an MPF gainmap.
        SkGainmapInfo info;
        if (!xmp->getGainmapInfoHDRGM(&info) && !xmp->getGainmapInfoHDRGainMap(&info)) {
            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);
        }
        *outInfo = info;
        return true;
    }
    return false;
}

bool SkJpegGetJpegRGainmap(const SkJpegXmp* xmp,
                           SkJpegSourceMgr* decoderSource,
                           SkGainmapInfo* outInfo,
                           std::unique_ptr<SkStream>* outGainmapImageStream) {
    // Parse the XMP metadata of the original image, to see if it specifies a RecoveryMap.
    SkGainmapInfo info;
    size_t itemOffsetFromEndOfImage = 0;
    size_t itemSize = 0;
    if (!xmp->getGainmapInfoJpegR(&info, &itemOffsetFromEndOfImage, &itemSize)) {
        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.
    const std::vector<SkJpegSegment>& segments = decoderSource->getAllSegments();
    if (segments.empty() || segments.back().marker != SkJpegSegmentScanner::kMarkerEndOfImage) {
        SkCodecPrintf("Failed to construct segments through EndOfImage.\n");
        return false;
    }
    const auto& lastSegment = segments.back();
    const size_t endOfImageOffset = lastSegment.offset + SkJpegSegmentScanner::kMarkerCodeSize;
    const size_t itemOffsetFromStartOfImage = endOfImageOffset + itemOffsetFromEndOfImage;

    // Extract the gainmap image's stream.
    auto gainmapImageStream = decoderSource->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);
    }

    *outInfo = info;
    return true;
}
