/*
 * 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

static bool gForceSkcmsForICCProfiles = true;

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;
}

void ICCProfileChromium::ForceSkcms(bool forceSkcms) {
    gForceSkcmsForICCProfiles = forceSkcms;
}

std::unique_ptr<ColorProfile> ColorProfile::MakeICCProfile(
        sk_sp<const SkData> data) {
    if (gForceSkcmsForICCProfiles) {
        return MakeICCProfileWithSkCMS(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
