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

#include "include/private/chromium/SkCodecsICCProfileChromium.h"
#include "modules/skcms/skcms.h"
#include "src/codec/SkCodecPriv.h"
#include "src/core/SkColorSpacePriv.h"

#if defined(SK_CODEC_COLOR_PROFILE_PARSE_WITH_RUST)
#include "src/codec/SkCodecColorProfileRust.h"
#endif

namespace SkCodecs {

namespace {

sk_sp<SkColorSpace> cicp_get_android_sk_color_space(uint8_t color_primaries,
                                                    uint8_t transfer_characteristics,
                                                    uint8_t matrix_coefficients,
                                                    uint8_t full_range_flag) {
    if (matrix_coefficients != 0) {
        return nullptr;
    }
    if (full_range_flag != 1) {
        return nullptr;
    }
    skcms_Matrix3x3 primaries;
    if (!SkNamedPrimaries::GetCicp(
            static_cast<SkNamedPrimaries::CicpId>(color_primaries), primaries)) {
        return nullptr;
    }
    skcms_TransferFunction trfn;
    if (!SkNamedTransferFn::GetCicp(
            static_cast<SkNamedTransferFn::CicpId>(transfer_characteristics), trfn)) {
        return nullptr;
    }
    switch (transfer_characteristics) {
        case 16:
            // Android expects PQ to match 203 nits to SDR white
            trfn = {-2.f, -1.55522297832f, 1.86045365631f, 32 / 2523.0f,
                    2413 / 128.0f, -2392 / 128.0f, 8192 / 1305.0f};
            break;
        case 18:
            // Android expects HLG to match 203 nits to SDR white
            skcms_TransferFunction_makeScaledHLGish(
                &trfn, 0.314509843f, 2.f, 2.f, 1.f / 0.17883277f, 0.28466892f, 0.55991073f);
            break;
        default:
            break;
    }
    return SkColorSpace::MakeRGB(trfn, primaries);
}

}  // namespace

std::unique_ptr<ColorProfile> ColorProfile::MakeICCProfileWithSkCMS(
        sk_sp<const SkData> data) {
    if (data) {
        skcms_ICCProfile profile;
        if (skcms_Parse(data->data(), data->size(), &profile)) {
            return std::unique_ptr<ColorProfile>(new ColorProfile(profile, std::move(data)));
        }
    }
    return nullptr;
}

std::unique_ptr<ColorProfile> ColorProfile::MakeICCProfile(
        sk_sp<const SkData> data) {
#if defined(SK_CODEC_COLOR_PROFILE_PARSE_WITH_RUST)
    return MakeICCProfileWithRust(data);
#else
    return MakeICCProfileWithSkCMS(data);
#endif
}

std::unique_ptr<ColorProfile> ColorProfile::Make(sk_sp<SkColorSpace> cs) {
    if (!cs) {
        return nullptr;
    }
    skcms_ICCProfile profile;
    cs->toProfile(&profile);
    return std::unique_ptr<ColorProfile>(new ColorProfile(profile));
}

std::unique_ptr<ColorProfile> ColorProfile::Make(
        const skcms_TransferFunction& trfn,
        const skcms_Matrix3x3& toXYZD50) {
    skcms_ICCProfile profile;
    skcms_Init(&profile);
    skcms_SetTransferFunction(&profile, &trfn);
    skcms_SetXYZD50(&profile, &toXYZD50);
    return std::unique_ptr<ColorProfile>(new ColorProfile(profile));
}

std::unique_ptr<ColorProfile> ColorProfile::MakeCICP(
        uint8_t color_primaries,
        uint8_t transfer_characteristics,
        uint8_t matrix_coefficients,
        uint8_t full_range_flag) {
    skcms_ICCProfile profile;
    skcms_Init(&profile);
    profile.has_CICP = true;
    profile.CICP.color_primaries = color_primaries;
    profile.CICP.transfer_characteristics = transfer_characteristics;
    profile.CICP.matrix_coefficients = matrix_coefficients;
    profile.CICP.video_full_range_flag = full_range_flag;
    return std::unique_ptr<ColorProfile>(new ColorProfile(profile));
}

std::unique_ptr<ColorProfile> ColorProfile::clone() const {
    auto cloned = std::unique_ptr<ColorProfile>(new ColorProfile(fProfile, fData));
    cloned->fRetainedData = fRetainedData;
    return cloned;
}

ColorProfile::DataSpace ColorProfile::dataSpace() const {
    switch (fProfile.data_color_space) {
        case skcms_Signature_RGB:
            return DataSpace::kRGB;
        case skcms_Signature_CMYK:
            return DataSpace::kCMYK;
        case skcms_Signature_Gray:
            return DataSpace::kGray;
        default:
            return DataSpace::kOther;
    }
}

sk_sp<SkColorSpace> ColorProfile::getExactColorSpace() const {
    return SkColorSpace::Make(fProfile);
}

sk_sp<SkColorSpace> ColorProfile::getAndroidOutputColorSpace() const {
    // Prefer CICP information if it exists.
    if (fProfile.has_CICP) {
        const auto cicpColorSpace = cicp_get_android_sk_color_space(
                fProfile.CICP.color_primaries,
                fProfile.CICP.transfer_characteristics,
                fProfile.CICP.matrix_coefficients,
                fProfile.CICP.video_full_range_flag);
        if (cicpColorSpace) {
            return cicpColorSpace;
        }
    }
    if (auto encodedSpace = SkColorSpace::Make(fProfile)) {
        // Leave the pixels in the encoded color space.  Color space conversion
        // will be handled after decode time.
        return encodedSpace;
    }
    if (fProfile.has_toXYZD50) {
        return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
                                     fProfile.toXYZD50);
    }
    return SkColorSpace::MakeSRGB();
}

ColorProfile::ColorProfile(const skcms_ICCProfile& profile, sk_sp<const SkData> data)
    : fProfile(profile)
    , fData(std::move(data))
{}

class ICCProfileChromiumImpl final : public ICCProfileChromium {
public:
    ICCProfileChromiumImpl(std::unique_ptr<ColorProfile> colorProfile)
        : fICCProfile(std::move(colorProfile)) {}

    const skcms_ICCProfile& GetProfile() const override {
        return *fICCProfile->profile();
    }

private:
    std::unique_ptr<ColorProfile> fICCProfile;
};

// static
std::unique_ptr<ICCProfileChromium>
ICCProfileChromium::Make(sk_sp<SkData> data) {
    auto profile = ColorProfile::MakeICCProfile(data);
    if (!profile) {
        return nullptr;
    }
    return std::make_unique<ICCProfileChromiumImpl>(std::move(profile));
}

}  // namespace SkCodecs
