#ifndef BNB_SAMPLE_CAMERA_GLSL
#define BNB_SAMPLE_CAMERA_GLSL

#include <bnb/color_spaces.glsl>

vec4 bnb_sample_camera(vec2 uv)
{
    vec4 result;
    if (bnb_rgba_camera.x < 0.5) {
        float Y = textureLod(BNB_SAMPLER_2D(tex_y), uv, 0.).x;

        if (bnb_camera_scale_i420.y < 0.5) {
            vec2 UV = textureLod(BNB_SAMPLER_2D(tex_uv), uv, 0.).xy;
            result = vec4(Y, UV.x, UV.y, 1.) * bnb_conversion_matrix;
        } else {
            float U = textureLod(BNB_SAMPLER_2D(tex_u), uv, 0.).x;
            float V = textureLod(BNB_SAMPLER_2D(tex_v), uv, 0.).x;

            result = vec4(Y, U, V, 1.) * bnb_conversion_matrix;
        }
    } else {
        result = textureLod(BNB_SAMPLER_2D(tex_rgb), uv, 0.);
        if (bnb_rgba_camera.z > 0.5) {
            result = result.bgra; // BGRA
        } else if (bnb_rgba_camera.w > 0.5) {
            result = result.gbar; // ARGB
        }
    }

#ifdef BNB_HAS_PARAM_tg_camera_correction
    int correction_mode = int(tg_camera_correction.x);
    // 0 off
    // 1 natural_color
    // 2 immersive_color
    // 3 vidid_color
    // 4 D55 -> D65
    // 5 D55 -> D75
    if (correction_mode == 4 || correction_mode == 5) {
        vec3 RGB = bnb_sRGB_to_linear(result.rgb);

        // RGB -> XYZ

        float X = dot(RGB, vec3(0.4124, 0.3576, 0.1805));
        float Y = dot(RGB, vec3(0.2126, 0.7152, 0.0722));
        float Z = dot(RGB, vec3(0.0193, 0.1192, 0.9505));

        // XYZ -> xyY

        float x = 0.;
        float y = 0.;
        float S = X + Y + Z;
        if (S != 0.) {
            x = X / S;
            y = Y / S;
        }

        if (correction_mode == 4) {
            x += -0.0197;
            y += -0.0184;
        } else {
            x += -0.0334;
            y += -0.03258;
        }

        // xyY -> XYZ

        if (y != 0.) {
            X = x * Y / y;
            Z = (1. - x - y) * Y / y;
        } else {
            X = 0.;
            Z = 0.;
        }

        // XYZ -> RGB linear

        RGB.r = 3.24062548 * X + (-1.53720797) * Y + (-0.4986286) * Z;
        RGB.g = -0.96893071 * X + 1.87575606 * Y + 0.04151752 * Z;
        RGB.b = 0.05571012 * X + (-0.20402105) * Y + 1.05699594 * Z;

        result.rgb = bnb_linear_to_sRGB(RGB);
    } else if (correction_mode != 0) {
        if (correction_mode == 1 || correction_mode == 3)
            result.rgb = pow(result.rgb, vec3(2.2 / 2.4));

        float y = 0.299 * result.r + 0.587 * result.g + 0.114 * result.b;
        float i = 0.59590059 * result.r - 0.27455667 * result.g - 0.32134392 * result.b;
        float q = 0.21153661 * result.r - 0.52273617 * result.g + 0.31119955 * result.b;

        float weight =
            clamp((q + 0.13) / 0.06 + 0.5, 0., 1.)
            * clamp(((correction_mode == 3 ? 0.03 : 0.) - q) / 0.06 + 0.5, 0., 1.)
            * clamp((y - 0.225) / 0.15 + 0.5, 0., 1.)
            * clamp((0.775 - y) / 0.15 + 0.5, 0., 1.);

        if (correction_mode == 3)
            i -= 0.03 * weight;
        q += 0.03 * weight;

        result.r = y + 0.95598634 * i + 0.6208248 * q;
        result.g = y - 0.27201283 * i - 0.64720424 * q;
        result.b = y - 1.10674021 * i + 1.70423049 * q;

        result.r = (result.r - 0.5) * 1.05 + 0.5;
        result.g = (result.g - 0.5) * 1.05 + 0.5;
        result.b = (result.b - 0.5) * 1.05 + 0.5;
    }
#endif

    return result;
}

#endif // BNB_SAMPLE_CAMERA_GLSL