// 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);

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* builtin = sem.Get(expr)->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 (sem.Get(expr)->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() {
    using f32 = ProgramBuilder::f32;
    ast::VariableList varList = {
        b.Param("v", b.ty.vec3<f32>()),
        b.Param("params", b.ty.type_name(gamma_transfer_struct_sym))};

    ast::StatementList statementList = {
        // 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"))};

    gamma_correction_sym = b.Symbols().New("gammaCorrection");

    b.Func(gamma_correction_sym, varList, b.ty.vec3<f32>(), statementList, {});
  }

  /// 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) {
    using f32 = ProgramBuilder::f32;
    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.0f);
      // textureSampleLevel(plane0, smp, coord.xy, 0.0);
      plane_0_call =
          b.Call("textureSampleLevel", "plane0", "smp", "coord", 0.0f);
      // textureSampleLevel(plane1, smp, coord.xy, 0.0);
      plane_1_call =
          b.Call("textureSampleLevel", "plane1", "smp", "coord", 0.0f);
    } else if (call_type == sem::BuiltinType::kTextureLoad) {
      // textureLoad(plane0, coords.xy, 0);
      single_plane_call = b.Call("textureLoad", "plane0", "coord", 0);
      // textureLoad(plane0, coords.xy, 0);
      plane_0_call = b.Call("textureLoad", "plane0", "coord", 0);
      // textureLoad(plane1, coords.xy, 0);
      plane_1_call = b.Call("textureLoad", "plane1", "coord", 0);
    } 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(1u)),
             b.Block(
                 // color = textureLoad(plane0, coord, 0).rgb;
                 b.Assign("color", b.MemberAccessor(single_plane_call, "rgb"))),
             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.0f),
                                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.0f);
        b.Return(b.vec4<f32>("color", 1.0f))};
  }

  /// 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.
      ast::VariableList varList = {
          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))};

      ast::StatementList statementList =
          createTexFnExtStatementList(sem::BuiltinType::kTextureSampleLevel);

      b.Func(texture_sample_external_sym, varList, b.ty.vec4(b.ty.f32()),
             statementList, {});
    }

    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.
      ast::VariableList var_list = {
          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))};

      ast::StatementList statement_list =
          createTexFnExtStatementList(sem::BuiltinType::kTextureLoad);

      b.Func(texture_load_external_sym, var_list, b.ty.vec4(b.ty.f32()),
             statement_list, {});
    }

    const ast::IdentifierExpression* exp = b.Expr(texture_load_external_sym);
    params = {plane_0_binding_param, b.Expr(syms.plane_1),
              ctx.Clone(expr->args[1]), b.Expr(syms.params)};
    return b.Call(exp, 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
