// Copyright 2021 The Tint Authors.
//
// 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 "src/tint/transform/multiplanar_external_texture.h"

#include <string>
#include <vector>

#include "src/tint/ast/function.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/call.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/variable.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::MultiplanarExternalTexture);
TINT_INSTANTIATE_TYPEINFO(tint::transform::MultiplanarExternalTexture::NewBindingPoints);

using namespace tint::number_suffixes;  // NOLINT

namespace tint::transform {
namespace {

/// This struct stores symbols for new bindings created as a result of
/// transforming a texture_external instance.
struct NewBindingSymbols {
    Symbol params;
    Symbol plane_0;
    Symbol plane_1;
};
}  // namespace

/// State holds the current transform state
struct MultiplanarExternalTexture::State {
    /// The clone context.
    CloneContext& ctx;

    /// ProgramBuilder for the context
    ProgramBuilder& b;

    /// Destination binding locations for the expanded texture_external provided
    /// as input into the transform.
    const NewBindingPoints* new_binding_points;

    /// Symbol for the GammaTransferParams
    Symbol gamma_transfer_struct_sym;

    /// Symbol for the ExternalTextureParams struct
    Symbol params_struct_sym;

    /// Symbol for the textureLoadExternal function
    Symbol texture_load_external_sym;

    /// Symbol for the textureSampleExternal function
    Symbol texture_sample_external_sym;

    /// Symbol for the gammaCorrection function
    Symbol gamma_correction_sym;

    /// Storage for new bindings that have been created corresponding to an
    /// original texture_external binding.
    std::unordered_map<const sem::Variable*, NewBindingSymbols> new_binding_symbols;

    /// Constructor
    /// @param context the clone
    /// @param newBindingPoints the input destination binding locations for the
    /// expanded texture_external
    State(CloneContext& context, const NewBindingPoints* newBindingPoints)
        : ctx(context), b(*context.dst), new_binding_points(newBindingPoints) {}

    /// Processes the module
    void Process() {
        auto& sem = ctx.src->Sem();

        // For each texture_external binding, we replace it with a texture_2d<f32>
        // binding and create two additional bindings (one texture_2d<f32> to
        // represent the secondary plane and one uniform buffer for the
        // ExternalTextureParams struct).
        for (auto* var : ctx.src->AST().GlobalVariables()) {
            auto* sem_var = sem.Get(var);
            if (!sem_var->Type()->UnwrapRef()->Is<sem::ExternalTexture>()) {
                continue;
            }

            // If the attributes are empty, then this must be a texture_external
            // passed as a function parameter. These variables are transformed
            // elsewhere.
            if (var->attributes.empty()) {
                continue;
            }

            // If we find a texture_external binding, we know we must emit the
            // ExternalTextureParams struct.
            if (!params_struct_sym.IsValid()) {
                createExtTexParamsStructs();
            }

            // The binding points for the newly introduced bindings must have been
            // provided to this transform. We fetch the new binding points by
            // providing the original texture_external binding points into the
            // passed map.
            BindingPoint bp = {var->BindingPoint().group->value,
                               var->BindingPoint().binding->value};

            BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp);
            if (it == new_binding_points->bindings_map.end()) {
                b.Diagnostics().add_error(
                    diag::System::Transform,
                    "missing new binding points for texture_external at binding {" +
                        std::to_string(bp.group) + "," + std::to_string(bp.binding) + "}");
                continue;
            }

            BindingPoints bps = it->second;

            // Symbols for the newly created bindings must be saved so they can be
            // passed as parameters later. These are placed in a map and keyed by
            // the source symbol associated with the texture_external binding that
            // corresponds with the new destination bindings.
            // NewBindingSymbols new_binding_syms;
            auto& syms = new_binding_symbols[sem_var];
            syms.plane_0 = ctx.Clone(var->symbol);
            syms.plane_1 = b.Symbols().New("ext_tex_plane_1");
            b.Global(syms.plane_1, b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32()),
                     b.GroupAndBinding(bps.plane_1.group, bps.plane_1.binding));
            syms.params = b.Symbols().New("ext_tex_params");
            b.Global(syms.params, b.ty.type_name("ExternalTextureParams"),
                     ast::StorageClass::kUniform,
                     b.GroupAndBinding(bps.params.group, bps.params.binding));

            // Replace the original texture_external binding with a texture_2d<f32>
            // binding.
            ast::AttributeList cloned_attributes = ctx.Clone(var->attributes);
            const ast::Expression* cloned_constructor = ctx.Clone(var->constructor);

            auto* replacement =
                b.Var(syms.plane_0, b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32()),
                      cloned_constructor, cloned_attributes);
            ctx.Replace(var, replacement);
        }

        // We must update all the texture_external parameters for user declared
        // functions.
        for (auto* fn : ctx.src->AST().Functions()) {
            for (const ast::Variable* param : fn->params) {
                if (auto* sem_var = sem.Get(param)) {
                    if (!sem_var->Type()->UnwrapRef()->Is<sem::ExternalTexture>()) {
                        continue;
                    }
                    // If we find a texture_external, we must ensure the
                    // ExternalTextureParams struct exists.
                    if (!params_struct_sym.IsValid()) {
                        createExtTexParamsStructs();
                    }
                    // When a texture_external is found, we insert all components
                    // the texture_external into the parameter list. We must also place
                    // the new symbols into the transform state so they can be used when
                    // transforming function calls.
                    auto& syms = new_binding_symbols[sem_var];
                    syms.plane_0 = ctx.Clone(param->symbol);
                    syms.plane_1 = b.Symbols().New("ext_tex_plane_1");
                    syms.params = b.Symbols().New("ext_tex_params");
                    auto tex2d_f32 = [&] {
                        return b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32());
                    };
                    ctx.Replace(param, b.Param(syms.plane_0, tex2d_f32()));
                    ctx.InsertAfter(fn->params, param, b.Param(syms.plane_1, tex2d_f32()));
                    ctx.InsertAfter(fn->params, param,
                                    b.Param(syms.params, b.ty.type_name(params_struct_sym)));
                }
            }
        }

        // Transform the original textureLoad and textureSampleLevel calls into
        // textureLoadExternal and textureSampleExternal calls.
        ctx.ReplaceAll([&](const ast::CallExpression* expr) -> const ast::CallExpression* {
            auto* call = sem.Get(expr)->UnwrapMaterialize()->As<sem::Call>();
            auto* builtin = call->Target()->As<sem::Builtin>();

            if (builtin && !builtin->Parameters().empty() &&
                builtin->Parameters()[0]->Type()->Is<sem::ExternalTexture>() &&
                builtin->Type() != sem::BuiltinType::kTextureDimensions) {
                if (auto* var_user = sem.Get<sem::VariableUser>(expr->args[0])) {
                    auto it = new_binding_symbols.find(var_user->Variable());
                    if (it == new_binding_symbols.end()) {
                        // If valid new binding locations were not provided earlier, we
                        // would have been unable to create these symbols. An error
                        // message was emitted earlier, so just return early to avoid
                        // internal compiler errors and retain a clean error message.
                        return nullptr;
                    }
                    auto& syms = it->second;

                    if (builtin->Type() == sem::BuiltinType::kTextureLoad) {
                        return createTexLdExt(expr, syms);
                    }

                    if (builtin->Type() == sem::BuiltinType::kTextureSampleLevel) {
                        return createTexSmpExt(expr, syms);
                    }
                }

            } else if (call->Target()->Is<sem::Function>()) {
                // The call expression may be to a user-defined function that
                // contains a texture_external parameter. These need to be expanded
                // out to multiple plane textures and the texture parameters
                // structure.
                for (auto* arg : expr->args) {
                    if (auto* var_user = sem.Get<sem::VariableUser>(arg)) {
                        // Check if a parameter is a texture_external by trying to find
                        // it in the transform state.
                        auto it = new_binding_symbols.find(var_user->Variable());
                        if (it != new_binding_symbols.end()) {
                            auto& syms = it->second;
                            // When we find a texture_external, we must unpack it into its
                            // components.
                            ctx.Replace(arg, b.Expr(syms.plane_0));
                            ctx.InsertAfter(expr->args, arg, b.Expr(syms.plane_1));
                            ctx.InsertAfter(expr->args, arg, b.Expr(syms.params));
                        }
                    }
                }
            }

            return nullptr;
        });
    }

    /// Creates the parameter structs associated with the transform.
    void createExtTexParamsStructs() {
        // Create GammaTransferParams struct.
        ast::StructMemberList gamma_transfer_member_list = {
            b.Member("G", b.ty.f32()), b.Member("A", b.ty.f32()),      b.Member("B", b.ty.f32()),
            b.Member("C", b.ty.f32()), b.Member("D", b.ty.f32()),      b.Member("E", b.ty.f32()),
            b.Member("F", b.ty.f32()), b.Member("padding", b.ty.u32())};

        gamma_transfer_struct_sym = b.Symbols().New("GammaTransferParams");

        b.Structure(gamma_transfer_struct_sym, gamma_transfer_member_list);

        // Create ExternalTextureParams struct.
        ast::StructMemberList ext_tex_params_member_list = {
            b.Member("numPlanes", b.ty.u32()),
            b.Member("yuvToRgbConversionMatrix", b.ty.mat3x4(b.ty.f32())),
            b.Member("gammaDecodeParams", b.ty.type_name("GammaTransferParams")),
            b.Member("gammaEncodeParams", b.ty.type_name("GammaTransferParams")),
            b.Member("gamutConversionMatrix", b.ty.mat3x3(b.ty.f32()))};

        params_struct_sym = b.Symbols().New("ExternalTextureParams");

        b.Structure(params_struct_sym, ext_tex_params_member_list);
    }

    /// Creates the gammaCorrection function if needed and returns a call
    /// expression to it.
    void createGammaCorrectionFn() {
        gamma_correction_sym = b.Symbols().New("gammaCorrection");

        b.Func(
            gamma_correction_sym,
            {
                b.Param("v", b.ty.vec3<f32>()),
                b.Param("params", b.ty.type_name(gamma_transfer_struct_sym)),
            },
            b.ty.vec3<f32>(),
            {
                // let cond = abs(v) < vec3(params.D);
                b.Decl(b.Let(
                    "cond", nullptr,
                    b.LessThan(b.Call("abs", "v"), b.vec3<f32>(b.MemberAccessor("params", "D"))))),
                // let t = sign(v) * ((params.C * abs(v)) + params.F);
                b.Decl(b.Let("t", nullptr,
                             b.Mul(b.Call("sign", "v"),
                                   b.Add(b.Mul(b.MemberAccessor("params", "C"), b.Call("abs", "v")),
                                         b.MemberAccessor("params", "F"))))),
                // let f = (sign(v) * pow(((params.A * abs(v)) + params.B),
                // vec3(params.G))) + params.E;
                b.Decl(b.Let("f", nullptr,
                             b.Mul(b.Call("sign", "v"),
                                   b.Add(b.Call("pow",
                                                b.Add(b.Mul(b.MemberAccessor("params", "A"),
                                                            b.Call("abs", "v")),
                                                      b.MemberAccessor("params", "B")),
                                                b.vec3<f32>(b.MemberAccessor("params", "G"))),
                                         b.MemberAccessor("params", "E"))))),
                // return select(f, t, cond);
                b.Return(b.Call("select", "f", "t", "cond")),
            });
    }

    /// Constructs a StatementList containing all the statements making up the
    /// bodies of the textureSampleExternal and textureLoadExternal functions.
    /// @param call_type determines which function body to generate
    /// @returns a statement list that makes of the body of the chosen function
    ast::StatementList createTexFnExtStatementList(sem::BuiltinType call_type) {
        const ast::CallExpression* single_plane_call = nullptr;
        const ast::CallExpression* plane_0_call = nullptr;
        const ast::CallExpression* plane_1_call = nullptr;
        if (call_type == sem::BuiltinType::kTextureSampleLevel) {
            // textureSampleLevel(plane0, smp, coord.xy, 0.0);
            single_plane_call = b.Call("textureSampleLevel", "plane0", "smp", "coord", 0_f);
            // textureSampleLevel(plane0, smp, coord.xy, 0.0);
            plane_0_call = b.Call("textureSampleLevel", "plane0", "smp", "coord", 0_f);
            // textureSampleLevel(plane1, smp, coord.xy, 0.0);
            plane_1_call = b.Call("textureSampleLevel", "plane1", "smp", "coord", 0_f);
        } else if (call_type == sem::BuiltinType::kTextureLoad) {
            // textureLoad(plane0, coords.xy, 0);
            single_plane_call = b.Call("textureLoad", "plane0", "coord", 0_i);
            // textureLoad(plane0, coords.xy, 0);
            plane_0_call = b.Call("textureLoad", "plane0", "coord", 0_i);
            // textureLoad(plane1, coords.xy, 0);
            plane_1_call = b.Call("textureLoad", "plane1", "coord", 0_i);
        } else {
            TINT_ICE(Transform, b.Diagnostics()) << "unhandled builtin: " << call_type;
        }

        return {
            // var color: vec3<f32>;
            b.Decl(b.Var("color", b.ty.vec3(b.ty.f32()))),
            // if ((params.numPlanes == 1u))
            b.If(b.create<ast::BinaryExpression>(
                     ast::BinaryOp::kEqual, b.MemberAccessor("params", "numPlanes"), b.Expr(1_u)),
                 b.Block(
                     // color = textureLoad(plane0, coord, 0).rgb;
                     b.Assign("color", b.MemberAccessor(single_plane_call, "rgb"))),
                 b.Else(b.Block(
                     // color = vec4<f32>(plane_0_call.r, plane_1_call.rg, 1.0) *
                     //         params.yuvToRgbConversionMatrix;
                     b.Assign("color",
                              b.Mul(b.vec4<f32>(b.MemberAccessor(plane_0_call, "r"),
                                                b.MemberAccessor(plane_1_call, "rg"), 1_f),
                                    b.MemberAccessor("params", "yuvToRgbConversionMatrix")))))),
            // color = gammaConversion(color, gammaDecodeParams);
            b.Assign("color", b.Call("gammaCorrection", "color",
                                     b.MemberAccessor("params", "gammaDecodeParams"))),
            // color = (params.gamutConversionMatrix * color);
            b.Assign("color", b.Mul(b.MemberAccessor("params", "gamutConversionMatrix"), "color")),
            // color = gammaConversion(color, gammaEncodeParams);
            b.Assign("color", b.Call("gammaCorrection", "color",
                                     b.MemberAccessor("params", "gammaEncodeParams"))),
            // return vec4<f32>(color, 1.f);
            b.Return(b.vec4<f32>("color", 1_f))};
    }

    /// Creates the textureSampleExternal function if needed and returns a call
    /// expression to it.
    /// @param expr the call expression being transformed
    /// @param syms the expanded symbols to be used in the new call
    /// @returns a call expression to textureSampleExternal
    const ast::CallExpression* createTexSmpExt(const ast::CallExpression* expr,
                                               NewBindingSymbols syms) {
        ast::ExpressionList params;
        const ast::Expression* plane_0_binding_param = ctx.Clone(expr->args[0]);

        if (expr->args.size() != 3) {
            TINT_ICE(Transform, b.Diagnostics()) << "expected textureSampleLevel call with a "
                                                    "texture_external to have 3 parameters, found "
                                                 << expr->args.size() << " parameters";
        }

        // TextureSampleExternal calls the gammaCorrection function, so ensure it
        // exists.
        if (!gamma_correction_sym.IsValid()) {
            createGammaCorrectionFn();
        }

        if (!texture_sample_external_sym.IsValid()) {
            texture_sample_external_sym = b.Symbols().New("textureSampleExternal");

            // Emit the textureSampleExternal function.
            b.Func(
                texture_sample_external_sym,
                {
                    b.Param("plane0", b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32())),
                    b.Param("plane1", b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32())),
                    b.Param("smp", b.ty.sampler(ast::SamplerKind::kSampler)),
                    b.Param("coord", b.ty.vec2(b.ty.f32())),
                    b.Param("params", b.ty.type_name(params_struct_sym)),
                },
                b.ty.vec4(b.ty.f32()),
                {
                    createTexFnExtStatementList(sem::BuiltinType::kTextureSampleLevel),
                });
        }

        const ast::IdentifierExpression* exp = b.Expr(texture_sample_external_sym);
        params = {plane_0_binding_param, b.Expr(syms.plane_1), ctx.Clone(expr->args[1]),
                  ctx.Clone(expr->args[2]), b.Expr(syms.params)};
        return b.Call(exp, params);
    }

    /// Creates the textureLoadExternal function if needed and returns a call
    /// expression to it.
    /// @param expr the call expression being transformed
    /// @param syms the expanded symbols to be used in the new call
    /// @returns a call expression to textureLoadExternal
    const ast::CallExpression* createTexLdExt(const ast::CallExpression* expr,
                                              NewBindingSymbols syms) {
        ast::ExpressionList params;
        const ast::Expression* plane_0_binding_param = ctx.Clone(expr->args[0]);

        if (expr->args.size() != 2) {
            TINT_ICE(Transform, b.Diagnostics())
                << "expected textureLoad call with a texture_external "
                   "to have 2 parameters, found "
                << expr->args.size() << " parameters";
        }

        // TextureLoadExternal calls the gammaCorrection function, so ensure it
        // exists.
        if (!gamma_correction_sym.IsValid()) {
            createGammaCorrectionFn();
        }

        if (!texture_load_external_sym.IsValid()) {
            texture_load_external_sym = b.Symbols().New("textureLoadExternal");

            // Emit the textureLoadExternal function.
            b.Func(
                texture_load_external_sym,
                {
                    b.Param("plane0", b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32())),
                    b.Param("plane1", b.ty.sampled_texture(ast::TextureDimension::k2d, b.ty.f32())),
                    b.Param("coord", b.ty.vec2(b.ty.i32())),
                    b.Param("params", b.ty.type_name(params_struct_sym)),
                },
                b.ty.vec4(b.ty.f32()),
                {
                    createTexFnExtStatementList(sem::BuiltinType::kTextureLoad),
                });
        }

        return b.Call(texture_load_external_sym, plane_0_binding_param, syms.plane_1,
                      ctx.Clone(expr->args[1]), syms.params);
    }
};

MultiplanarExternalTexture::NewBindingPoints::NewBindingPoints(BindingsMap inputBindingsMap)
    : bindings_map(std::move(inputBindingsMap)) {}
MultiplanarExternalTexture::NewBindingPoints::~NewBindingPoints() = default;

MultiplanarExternalTexture::MultiplanarExternalTexture() = default;
MultiplanarExternalTexture::~MultiplanarExternalTexture() = default;

bool MultiplanarExternalTexture::ShouldRun(const Program* program, const DataMap&) const {
    for (auto* node : program->ASTNodes().Objects()) {
        if (auto* ty = node->As<ast::Type>()) {
            if (program->Sem().Get<sem::ExternalTexture>(ty)) {
                return true;
            }
        }
    }
    return false;
}

// Within this transform, an instance of a texture_external binding is unpacked
// into two texture_2d<f32> bindings representing two possible planes of a
// single texture and a uniform buffer binding representing a struct of
// parameters. Calls to textureLoad or textureSampleLevel that contain a
// texture_external parameter will be transformed into a newly generated version
// of the function, which can perform the desired operation on a single RGBA
// plane or on separate Y and UV planes.
void MultiplanarExternalTexture::Run(CloneContext& ctx, const DataMap& inputs, DataMap&) const {
    auto* new_binding_points = inputs.Get<NewBindingPoints>();

    if (!new_binding_points) {
        ctx.dst->Diagnostics().add_error(
            diag::System::Transform,
            "missing new binding point data for " + std::string(TypeInfo().name));
        return;
    }

    State state(ctx, new_binding_points);

    state.Process();

    ctx.Clone();
}

}  // namespace tint::transform
