// Copyright 2022 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/transform/combine_samplers.h"

#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "src/sem/function.h"
#include "src/sem/statement.h"

#include "src/utils/map.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::CombineSamplers);
TINT_INSTANTIATE_TYPEINFO(tint::transform::CombineSamplers::BindingInfo);

namespace {

bool IsGlobal(const tint::sem::VariablePair& pair) {
  return pair.first->Is<tint::sem::GlobalVariable>() &&
         (!pair.second || pair.second->Is<tint::sem::GlobalVariable>());
}

}  // namespace

namespace tint {
namespace transform {

CombineSamplers::BindingInfo::BindingInfo(const BindingMap& map)
    : binding_map(map) {}
CombineSamplers::BindingInfo::BindingInfo(const BindingInfo& other) = default;
CombineSamplers::BindingInfo::~BindingInfo() = default;

/// The PIMPL state for the CombineSamplers transform
struct CombineSamplers::State {
  /// The clone context
  CloneContext& ctx;

  /// The binding info
  const BindingInfo* binding_info;

  /// Map from a texture/sampler pair to the corresponding combined sampler
  /// variable
  using CombinedTextureSamplerMap =
      std::unordered_map<sem::VariablePair, const ast::Variable*>;

  /// Use sem::BindingPoint without scope.
  using BindingPoint = sem::BindingPoint;

  /// A map of all global texture/sampler variable pairs to the global
  /// combined sampler variable that will replace it.
  CombinedTextureSamplerMap global_combined_texture_samplers_;

  /// A map of all texture/sampler variable pairs that contain a function
  /// parameter to the combined sampler function paramter that will replace it.
  std::unordered_map<const sem::Function*, CombinedTextureSamplerMap>
      function_combined_texture_samplers_;

  /// Placeholder global samplers used when a function contains texture-only
  /// references (one comparison sampler, one regular). These are also used as
  /// temporary sampler parameters to the texture intrinsics to satsify the WGSL
  /// resolver, but are then ignored and removed by the GLSL writer.
  const ast::Variable* placeholder_samplers_[2] = {};

  /// Group and binding decorations used by all combined sampler globals.
  /// Group 0 and binding 0 are used, with collisions disabled.
  /// @returns the newly-created decoration list
  ast::DecorationList Decorations() const {
    auto decorations = ctx.dst->GroupAndBinding(0, 0);
    decorations.push_back(
        ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision));
    return decorations;
  }

  /// Constructor
  /// @param context the clone context
  /// @param info the binding map information
  State(CloneContext& context, const BindingInfo* info)
      : ctx(context), binding_info(info) {}

  /// Creates a combined sampler global variables.
  /// (Note this is actually a Texture node at the AST level, but it will be
  /// written as the corresponding sampler (eg., sampler2D) on GLSL output.)
  /// @param texture_var the texture (global) variable
  /// @param sampler_var the sampler (global) variable
  /// @param name the default name to use (may be overridden by map lookup)
  /// @returns the newly-created global variable
  const ast::Variable* CreateCombinedGlobal(const sem::Variable* texture_var,
                                            const sem::Variable* sampler_var,
                                            std::string name) {
    SamplerTexturePair bp_pair;
    bp_pair.texture_binding_point =
        texture_var->As<sem::GlobalVariable>()->BindingPoint();
    bp_pair.sampler_binding_point =
        sampler_var ? sampler_var->As<sem::GlobalVariable>()->BindingPoint()
                    : BindingPoint();
    auto it = binding_info->binding_map.find(bp_pair);
    if (it != binding_info->binding_map.end()) {
      name = it->second;
    }
    const ast::Type* type = CreateASTTypeFor(ctx, texture_var->Type());
    Symbol symbol = ctx.dst->Symbols().New(name);
    return ctx.dst->Global(symbol, type, Decorations());
  }

  /// Creates placeholder global sampler variables.
  /// @param kind the sampler kind to create for
  /// @returns the newly-created global variable
  const ast::Variable* CreatePlaceholder(ast::SamplerKind kind) {
    const ast::Type* type = ctx.dst->ty.sampler(kind);
    const char* name = kind == ast::SamplerKind::kComparisonSampler
                           ? "placeholder_comparison_sampler"
                           : "placeholder_sampler";
    Symbol symbol = ctx.dst->Symbols().New(name);
    return ctx.dst->Global(symbol, type, Decorations());
  }

  /// Performs the transformation
  void Run() {
    auto& sem = ctx.src->Sem();

    // Remove all texture and sampler global variables. These will be replaced
    // by combined samplers.
    for (auto* var : ctx.src->AST().GlobalVariables()) {
      if (sem.Get(var->type)->IsAnyOf<sem::Texture, sem::Sampler>()) {
        ctx.Remove(ctx.src->AST().GlobalDeclarations(), var);
      }
    }

    // Rewrite all function signatures to use combined samplers, and remove
    // separate textures & samplers. Create new combined globals where found.
    ctx.ReplaceAll([&](const ast::Function* src) -> const ast::Function* {
      if (auto* func = sem.Get(src)) {
        auto pairs = func->TextureSamplerPairs();
        if (pairs.empty()) {
          return nullptr;
        }
        ast::VariableList params;
        for (auto pair : func->TextureSamplerPairs()) {
          const sem::Variable* texture_var = pair.first;
          const sem::Variable* sampler_var = pair.second;
          std::string name =
              ctx.src->Symbols().NameFor(texture_var->Declaration()->symbol);
          if (sampler_var) {
            name += "_" + ctx.src->Symbols().NameFor(
                              sampler_var->Declaration()->symbol);
          }
          if (IsGlobal(pair)) {
            // Both texture and sampler are global; add a new global variable
            // to represent the combined sampler (if not already created).
            utils::GetOrCreate(global_combined_texture_samplers_, pair, [&] {
              return CreateCombinedGlobal(texture_var, sampler_var, name);
            });
          } else {
            // Either texture or sampler (or both) is a function parameter;
            // add a new function parameter to represent the combined sampler.
            const ast::Type* type = CreateASTTypeFor(ctx, texture_var->Type());
            const ast::Variable* var =
                ctx.dst->Param(ctx.dst->Symbols().New(name), type);
            params.push_back(var);
            function_combined_texture_samplers_[func][pair] = var;
          }
        }
        // Filter out separate textures and samplers from the original
        // function signature.
        for (auto* var : src->params) {
          if (!sem.Get(var->type)->IsAnyOf<sem::Texture, sem::Sampler>()) {
            params.push_back(ctx.Clone(var));
          }
        }
        // Create a new function signature that differs only in the parameter
        // list.
        auto symbol = ctx.Clone(src->symbol);
        auto* return_type = ctx.Clone(src->return_type);
        auto* body = ctx.Clone(src->body);
        auto decorations = ctx.Clone(src->decorations);
        auto return_type_decorations = ctx.Clone(src->return_type_decorations);
        return ctx.dst->create<ast::Function>(
            symbol, params, return_type, body, std::move(decorations),
            std::move(return_type_decorations));
      }
      return nullptr;
    });

    // Replace all function call expressions containing texture or
    // sampler parameters to use the current function's combined samplers or
    // the combined global samplers, as appropriate.
    ctx.ReplaceAll([&](const ast::CallExpression* expr)
                       -> const ast::Expression* {
      if (auto* call = sem.Get(expr)) {
        ast::ExpressionList args;
        // Replace all texture intrinsic calls.
        if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
          const auto& signature = intrinsic->Signature();
          int sampler_index = signature.IndexOf(sem::ParameterUsage::kSampler);
          int texture_index = signature.IndexOf(sem::ParameterUsage::kTexture);
          if (texture_index == -1) {
            return nullptr;
          }
          const sem::Expression* texture = call->Arguments()[texture_index];
          const sem::Expression* sampler =
              sampler_index != -1 ? call->Arguments()[sampler_index] : nullptr;
          auto* texture_var = texture->As<sem::VariableUser>()->Variable();
          auto* sampler_var =
              sampler ? sampler->As<sem::VariableUser>()->Variable() : nullptr;
          sem::VariablePair new_pair(texture_var, sampler_var);
          for (auto* arg : expr->args) {
            auto* type = ctx.src->TypeOf(arg)->UnwrapRef();
            if (type->Is<sem::Texture>()) {
              const ast::Variable* var =
                  IsGlobal(new_pair)
                      ? global_combined_texture_samplers_[new_pair]
                      : function_combined_texture_samplers_
                            [call->Stmt()->Function()][new_pair];
              args.push_back(ctx.dst->Expr(var->symbol));
            } else if (auto* sampler_type = type->As<sem::Sampler>()) {
              ast::SamplerKind kind = sampler_type->kind();
              int index = (kind == ast::SamplerKind::kSampler) ? 0 : 1;
              const ast::Variable*& p = placeholder_samplers_[index];
              if (!p) {
                p = CreatePlaceholder(kind);
              }
              args.push_back(ctx.dst->Expr(p->symbol));
            } else {
              args.push_back(ctx.Clone(arg));
            }
          }
          return ctx.dst->Call(ctx.Clone(expr->target.name), args);
        }
        // Replace all function calls.
        if (auto* callee = call->Target()->As<sem::Function>()) {
          for (auto pair : callee->TextureSamplerPairs()) {
            // Global pairs used by the callee do not require a function
            // parameter at the call site.
            if (IsGlobal(pair)) {
              continue;
            }
            const sem::Variable* texture_var = pair.first;
            const sem::Variable* sampler_var = pair.second;
            if (auto* param = texture_var->As<sem::Parameter>()) {
              const sem::Expression* texture =
                  call->Arguments()[param->Index()];
              texture_var = texture->As<sem::VariableUser>()->Variable();
            }
            if (sampler_var) {
              if (auto* param = sampler_var->As<sem::Parameter>()) {
                const sem::Expression* sampler =
                    call->Arguments()[param->Index()];
                sampler_var = sampler->As<sem::VariableUser>()->Variable();
              }
            }
            sem::VariablePair new_pair(texture_var, sampler_var);
            // If both texture and sampler are (now) global, pass that
            // global variable to the callee. Otherwise use the caller's
            // function parameter for this pair.
            const ast::Variable* var =
                IsGlobal(new_pair) ? global_combined_texture_samplers_[new_pair]
                                   : function_combined_texture_samplers_
                                         [call->Stmt()->Function()][new_pair];
            auto* arg = ctx.dst->Expr(var->symbol);
            args.push_back(arg);
          }
          // Append all of the remaining non-texture and non-sampler
          // parameters.
          for (auto* arg : expr->args) {
            if (!ctx.src->TypeOf(arg)
                     ->UnwrapRef()
                     ->IsAnyOf<sem::Texture, sem::Sampler>()) {
              args.push_back(ctx.Clone(arg));
            }
          }
          return ctx.dst->Call(ctx.Clone(expr->target.name), args);
        }
      }
      return nullptr;
    });

    ctx.Clone();
  }
};

CombineSamplers::CombineSamplers() = default;

CombineSamplers::~CombineSamplers() = default;

void CombineSamplers::Run(CloneContext& ctx, const DataMap& inputs, DataMap&) {
  auto* binding_info = inputs.Get<BindingInfo>();
  if (!binding_info) {
    ctx.dst->Diagnostics().add_error(
        diag::System::Transform,
        "missing transform data for " + std::string(TypeInfo().name));
    return;
  }

  State(ctx, binding_info).Run();
}

}  // namespace transform
}  // namespace tint
