/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ScreenCaptureOutput.h"
#include "ScreenCaptureRenderSurface.h"
#include "common/include/common/FlagManager.h"
#include "ui/Rotation.h"

#include <compositionengine/CompositionEngine.h>
#include <compositionengine/DisplayColorProfileCreationArgs.h>
#include <compositionengine/impl/DisplayColorProfile.h>
#include <ui/HdrRenderTypeUtils.h>
#include <ui/Rotation.h>

namespace android {

std::shared_ptr<ScreenCaptureOutput> createScreenCaptureOutput(ScreenCaptureOutputArgs args) {
    std::shared_ptr<ScreenCaptureOutput> output = compositionengine::impl::createOutputTemplated<
            ScreenCaptureOutput, compositionengine::CompositionEngine,
            /* sourceCrop */ const Rect, ftl::Optional<DisplayIdVariant>,
            const compositionengine::Output::ColorProfile&,
            /* layerAlpha */ float,
            /* disableBlur */ bool>(args.compositionEngine, args.sourceCrop, args.displayIdVariant,
                                    args.colorProfile, args.layerAlpha, args.disableBlur,
                                    args.dimInGammaSpaceForEnhancedScreenshots,
                                    args.enableLocalTonemapping);
    output->editState().isSecure = args.isSecure;
    output->editState().isProtected = args.buffer->getUsage() & GRALLOC_USAGE_PROTECTED;
    output->setCompositionEnabled(true);
    output->setLayerFilter(
            {.layerStack = args.layerStack, .toInternalDisplay = false, .skipScreenshot = true});
    output->setRenderSurface(std::make_unique<ScreenCaptureRenderSurface>(std::move(args.buffer)));
    output->setDisplayBrightness(args.sdrWhitePointNits, args.displayBrightnessNits);
    output->editState().clientTargetBrightness = args.targetBrightness;
    output->editState().treat170mAsSrgb = args.treat170mAsSrgb;

    output->setDisplayColorProfile(std::make_unique<compositionengine::impl::DisplayColorProfile>(
            compositionengine::DisplayColorProfileCreationArgsBuilder()
                    .setHasWideColorGamut(true)
                    .Build()));

    const Rect& sourceCrop = args.sourceCrop;
    const ui::Rotation orientation = ui::ROTATION_0;
    output->setDisplaySize({sourceCrop.getWidth(), sourceCrop.getHeight()});
    output->setProjection(orientation, sourceCrop,
                          {args.reqBufferSize.width, args.reqBufferSize.height});
    output->setName(args.debugName);
    return output;
}

ScreenCaptureOutput::ScreenCaptureOutput(
        const Rect sourceCrop, ftl::Optional<DisplayIdVariant> displayIdVariant,
        const compositionengine::Output::ColorProfile& colorProfile, float layerAlpha,
        bool disableBlur, bool dimInGammaSpaceForEnhancedScreenshots, bool enableLocalTonemapping)
      : mSourceCrop(sourceCrop),
        mDisplayIdVariant(displayIdVariant),
        mColorProfile(colorProfile),
        mLayerAlpha(layerAlpha),
        mDisableBlur(disableBlur),
        mDimInGammaSpaceForEnhancedScreenshots(dimInGammaSpaceForEnhancedScreenshots),
        mEnableLocalTonemapping(enableLocalTonemapping) {}

void ScreenCaptureOutput::updateColorProfile(const compositionengine::CompositionRefreshArgs&) {
    auto& outputState = editState();
    outputState.dataspace = mColorProfile.dataspace;
    outputState.renderIntent = mColorProfile.renderIntent;
}

renderengine::DisplaySettings ScreenCaptureOutput::generateClientCompositionDisplaySettings(
        const std::shared_ptr<renderengine::ExternalTexture>& buffer) const {
    auto clientCompositionDisplay =
            compositionengine::impl::Output::generateClientCompositionDisplaySettings(buffer);
    clientCompositionDisplay.clip = mSourceCrop;

    auto renderIntent = static_cast<ui::RenderIntent>(clientCompositionDisplay.renderIntent);
    if (mDimInGammaSpaceForEnhancedScreenshots && renderIntent != ui::RenderIntent::COLORIMETRIC &&
        renderIntent != ui::RenderIntent::TONE_MAP_COLORIMETRIC) {
        clientCompositionDisplay.dimmingStage =
                aidl::android::hardware::graphics::composer3::DimmingStage::GAMMA_OETF;
    }

    if (mEnableLocalTonemapping) {
        clientCompositionDisplay.tonemapStrategy =
                renderengine::DisplaySettings::TonemapStrategy::Local;
    }

        if (static_cast<ui::PixelFormat>(buffer->getPixelFormat()) == ui::PixelFormat::RGBA_FP16) {
            clientCompositionDisplay.targetHdrSdrRatio =
                    getState().displayBrightnessNits / getState().sdrWhitePointNits;
        } else {
            clientCompositionDisplay.targetHdrSdrRatio = 1.f;
        }

    return clientCompositionDisplay;
}

const aidl::android::hardware::graphics::composer3::OverlayProperties*
ScreenCaptureOutput::getOverlaySupport() {
    return &getCompositionEngine().getHwComposer().getOverlaySupport();
}

std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts>
ScreenCaptureOutput::generateLuts() {
    std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> lutsMapper;
    if (FlagManager::getInstance().luts_api()) {
        std::vector<sp<GraphicBuffer>> buffers;
        std::vector<int32_t> layerIds;

        for (const auto* layer : getOutputLayersOrderedByZ()) {
            const auto& layerState = layer->getState();
            const auto* layerFEState = layer->getLayerFE().getCompositionState();
            auto pixelFormat = layerFEState->buffer
                    ? std::make_optional(
                              static_cast<ui::PixelFormat>(layerFEState->buffer->getPixelFormat()))
                    : std::nullopt;
            const auto hdrType = getHdrRenderType(layerState.dataspace, pixelFormat,
                                                  layerFEState->desiredHdrSdrRatio);
            std::optional<std::vector<uint8_t>> smpte2094_50;
            const bool hasAgtm = layerFEState->buffer &&
                    layerFEState->buffer->getSmpte2094_50(&smpte2094_50) == OK && smpte2094_50;
            if (layerFEState->buffer && !layerFEState->luts && !hasAgtm &&
                hdrType == HdrRenderType::GENERIC_HDR) {
                buffers.push_back(layerFEState->buffer);
                layerIds.push_back(layer->getLayerFE().getSequence());
            }
        }

        // only call getLuts if buffers are not empty
        if (!buffers.empty()) {
            std::vector<aidl::android::hardware::graphics::composer3::Luts> luts;
            if (const auto physicalDisplayId = mDisplayIdVariant.and_then(asPhysicalDisplayId)) {
                auto& hwc = getCompositionEngine().getHwComposer();
                hwc.getLuts(*physicalDisplayId, buffers, &luts);
            }

            if (buffers.size() == luts.size()) {
                for (size_t i = 0; i < luts.size(); i++) {
                    lutsMapper[layerIds[i]] = std::move(luts[i]);
                }
            }
        }
    }
    return lutsMapper;
}

std::vector<compositionengine::LayerFE::LayerSettings>
ScreenCaptureOutput::generateClientCompositionRequests(
        bool supportsProtectedContent, ui::Dataspace outputDataspace,
        std::vector<compositionengine::LayerFE*>& outLayerFEs) {
    // This map maps the layer unique id to a Lut
    std::unordered_map<int32_t, aidl::android::hardware::graphics::composer3::Luts> lutsMapper =
            generateLuts();

    auto clientCompositionLayers = compositionengine::impl::Output::
            generateClientCompositionRequests(supportsProtectedContent, outputDataspace,
                                              outLayerFEs);

    for (auto& layer : clientCompositionLayers) {
        if (lutsMapper.find(layer.sequence) != lutsMapper.end()) {
            auto& aidlLuts = lutsMapper[layer.sequence];
            if (aidlLuts.pfd.get() >= 0 && aidlLuts.offsets) {
                std::vector<int32_t> offsets = *aidlLuts.offsets;
                std::vector<int32_t> dimensions;
                dimensions.reserve(offsets.size());
                std::vector<int32_t> sizes;
                sizes.reserve(offsets.size());
                std::vector<int32_t> keys;
                keys.reserve(offsets.size());
                for (size_t j = 0; j < offsets.size(); j++) {
                    dimensions.emplace_back(
                            static_cast<int32_t>(aidlLuts.lutProperties[j].dimension));
                    sizes.emplace_back(aidlLuts.lutProperties[j].size);
                    keys.emplace_back(
                            static_cast<int32_t>(aidlLuts.lutProperties[j].samplingKeys[0]));
                }
                layer.luts = std::make_shared<gui::DisplayLuts>(base::unique_fd(
                                                                        aidlLuts.pfd.release()),
                                                                offsets, dimensions, sizes, keys);
            }
        }
    }

    if (mDisableBlur) {
        for (auto& layer : clientCompositionLayers) {
            layer.backgroundBlurRadius = 0;
            layer.blurRegions.clear();
        }
    }

    if (outputDataspace == ui::Dataspace::BT2020_HLG) {
        for (auto& layer : clientCompositionLayers) {
            auto transfer = layer.sourceDataspace & ui::Dataspace::TRANSFER_MASK;
            if (transfer != static_cast<int32_t>(ui::Dataspace::TRANSFER_HLG) &&
                transfer != static_cast<int32_t>(ui::Dataspace::TRANSFER_ST2084)) {
                layer.whitePointNits *= (1000.0f / 203.0f);
            }
        }
    }

    compositionengine::LayerFE::LayerSettings fillLayer;
    fillLayer.name = "ScreenCaptureFillLayer";
    fillLayer.source.buffer.buffer = nullptr;
    fillLayer.source.solidColor = half3(0.0f, 0.0f, 0.0f);
    fillLayer.geometry.boundaries =
            FloatRect(static_cast<float>(mSourceCrop.left), static_cast<float>(mSourceCrop.top),
                      static_cast<float>(mSourceCrop.right),
                      static_cast<float>(mSourceCrop.bottom));

    fillLayer.alpha = half(mLayerAlpha);
    clientCompositionLayers.insert(clientCompositionLayers.begin(), fillLayer);

    return clientCompositionLayers;
}

} // namespace android