// Copyright 2020 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/first_index_offset.h"

#include <memory>
#include <unordered_map>
#include <utility>

#include "src/ast/struct_block_decoration.h"
#include "src/program_builder.h"
#include "src/sem/function.h"
#include "src/sem/member_accessor_expression.h"
#include "src/sem/struct.h"
#include "src/sem/variable.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::FirstIndexOffset::BindingPoint);
TINT_INSTANTIATE_TYPEINFO(tint::transform::FirstIndexOffset::Data);

namespace tint {
namespace transform {
namespace {

// Uniform buffer member names
constexpr char kFirstVertexName[] = "first_vertex_index";
constexpr char kFirstInstanceName[] = "first_instance_index";

}  // namespace

FirstIndexOffset::BindingPoint::BindingPoint() = default;
FirstIndexOffset::BindingPoint::BindingPoint(uint32_t b, uint32_t g)
    : binding(b), group(g) {}
FirstIndexOffset::BindingPoint::~BindingPoint() = default;

FirstIndexOffset::Data::Data(bool has_vtx_index,
                             bool has_inst_index,
                             uint32_t first_vtx_offset,
                             uint32_t first_inst_offset)
    : has_vertex_index(has_vtx_index),
      has_instance_index(has_inst_index),
      first_vertex_offset(first_vtx_offset),
      first_instance_offset(first_inst_offset) {}
FirstIndexOffset::Data::Data(const Data&) = default;
FirstIndexOffset::Data::~Data() = default;

FirstIndexOffset::FirstIndexOffset() = default;
FirstIndexOffset::FirstIndexOffset(uint32_t binding, uint32_t group)
    : binding_(binding), group_(group) {}

FirstIndexOffset::~FirstIndexOffset() = default;

Output FirstIndexOffset::Run(const Program* in, const DataMap& data) {
  // Get the uniform buffer binding point
  uint32_t ub_binding = binding_;
  uint32_t ub_group = group_;
  if (auto* binding_point = data.Get<BindingPoint>()) {
    ub_binding = binding_point->binding;
    ub_group = binding_point->group;
  }

  ProgramBuilder out;
  CloneContext ctx(&out, in);

  // Map of builtin usages
  std::unordered_map<const sem::Variable*, const char*> builtin_vars;
  std::unordered_map<const sem::StructMember*, const char*> builtin_members;

  bool has_vertex_index = false;
  bool has_instance_index = false;

  // Traverse the AST scanning for builtin accesses via variables (includes
  // parameters) or structure member accesses.
  for (auto* node : in->ASTNodes().Objects()) {
    if (auto* var = node->As<ast::Variable>()) {
      for (ast::Decoration* dec : var->decorations()) {
        if (auto* builtin_dec = dec->As<ast::BuiltinDecoration>()) {
          ast::Builtin builtin = builtin_dec->value();
          if (builtin == ast::Builtin::kVertexIndex) {
            auto* sem_var = ctx.src->Sem().Get(var);
            builtin_vars.emplace(sem_var, kFirstVertexName);
            has_vertex_index = true;
          }
          if (builtin == ast::Builtin::kInstanceIndex) {
            auto* sem_var = ctx.src->Sem().Get(var);
            builtin_vars.emplace(sem_var, kFirstInstanceName);
            has_instance_index = true;
          }
        }
      }
    }
    if (auto* member = node->As<ast::StructMember>()) {
      for (ast::Decoration* dec : member->decorations()) {
        if (auto* builtin_dec = dec->As<ast::BuiltinDecoration>()) {
          ast::Builtin builtin = builtin_dec->value();
          if (builtin == ast::Builtin::kVertexIndex) {
            auto* sem_mem = ctx.src->Sem().Get(member);
            builtin_members.emplace(sem_mem, kFirstVertexName);
            has_vertex_index = true;
          }
          if (builtin == ast::Builtin::kInstanceIndex) {
            auto* sem_mem = ctx.src->Sem().Get(member);
            builtin_members.emplace(sem_mem, kFirstInstanceName);
            has_instance_index = true;
          }
        }
      }
    }
  }

  // Byte offsets on the uniform buffer
  uint32_t vertex_index_offset = 0;
  uint32_t instance_index_offset = 0;

  if (has_vertex_index || has_instance_index) {
    // Add uniform buffer members and calculate byte offsets
    uint32_t offset = 0;
    ast::StructMemberList members;
    if (has_vertex_index) {
      members.push_back(ctx.dst->Member(kFirstVertexName, ctx.dst->ty.u32()));
      vertex_index_offset = offset;
      offset += 4;
    }
    if (has_instance_index) {
      members.push_back(ctx.dst->Member(kFirstInstanceName, ctx.dst->ty.u32()));
      instance_index_offset = offset;
      offset += 4;
    }
    auto struct_type =
        ctx.dst->Structure(ctx.dst->Symbols().New(), std::move(members),
                           {ctx.dst->create<ast::StructBlockDecoration>()});

    // Create a global to hold the uniform buffer
    Symbol buffer_name = ctx.dst->Symbols().New();
    ctx.dst->Global(buffer_name, struct_type, ast::StorageClass::kUniform,
                    nullptr,
                    ast::DecorationList{
                        ctx.dst->create<ast::BindingDecoration>(ub_binding),
                        ctx.dst->create<ast::GroupDecoration>(ub_group),
                    });

    // Fix up all references to the builtins with the offsets
    ctx.ReplaceAll([=, &ctx](ast::Expression* expr) -> ast::Expression* {
      auto* sem = ctx.src->Sem().Get(expr);
      if (auto* user = sem->As<sem::VariableUser>()) {
        auto it = builtin_vars.find(user->Variable());
        if (it != builtin_vars.end()) {
          return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
                              ctx.dst->MemberAccessor(buffer_name, it->second));
        }
      }
      if (auto* access = sem->As<sem::StructMemberAccess>()) {
        auto it = builtin_members.find(access->Member());
        if (it != builtin_members.end()) {
          return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
                              ctx.dst->MemberAccessor(buffer_name, it->second));
        }
      }
      // Not interested in this experssion. Just clone.
      return nullptr;
    });
  }

  ctx.Clone();

  return Output(
      Program(std::move(out)),
      std::make_unique<Data>(has_vertex_index, has_instance_index,
                             vertex_index_offset, instance_index_offset));
}

}  // namespace transform
}  // namespace tint
