// 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/semantic/function.h"
#include "src/semantic/member_accessor_expression.h"
#include "src/semantic/struct.h"
#include "src/semantic/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;

Transform::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 semantic::Variable*, const char*> builtin_vars;
  std::unordered_map<const semantic::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<semantic::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<semantic::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
