// 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/transform/add_spirv_block_decoration.h"

#include <unordered_map>
#include <unordered_set>
#include <utility>

#include "src/program_builder.h"
#include "src/sem/variable.h"
#include "src/utils/map.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::AddSpirvBlockDecoration);
TINT_INSTANTIATE_TYPEINFO(
    tint::transform::AddSpirvBlockDecoration::SpirvBlockDecoration);

namespace tint {
namespace transform {

AddSpirvBlockDecoration::AddSpirvBlockDecoration() = default;

AddSpirvBlockDecoration::~AddSpirvBlockDecoration() = default;

void AddSpirvBlockDecoration::Run(CloneContext& ctx, const DataMap&, DataMap&) {
  auto& sem = ctx.src->Sem();

  // Collect the set of structs that are nested in other types.
  std::unordered_set<const sem::Struct*> nested_structs;
  for (auto* node : ctx.src->ASTNodes().Objects()) {
    if (auto* arr = sem.Get<sem::Array>(node->As<ast::Array>())) {
      if (auto* nested_str = arr->ElemType()->As<sem::Struct>()) {
        nested_structs.insert(nested_str);
      }
    } else if (auto* str = sem.Get<sem::Struct>(node->As<ast::Struct>())) {
      for (auto* member : str->Members()) {
        if (auto* nested_str = member->Type()->As<sem::Struct>()) {
          nested_structs.insert(nested_str);
        }
      }
    }
  }

  // A map from a type in the source program to a block-decorated wrapper that
  // contains it in the destination program.
  std::unordered_map<const sem::Type*, const ast::Struct*> wrapper_structs;

  // Process global variables that are buffers.
  for (auto* var : ctx.src->AST().GlobalVariables()) {
    auto* sem_var = sem.Get<sem::GlobalVariable>(var);
    if (var->declared_storage_class != ast::StorageClass::kStorage &&
        var->declared_storage_class != ast::StorageClass::kUniform) {
      continue;
    }

    auto* ty = sem.Get(var->type);
    auto* str = ty->As<sem::Struct>();
    if (!str || nested_structs.count(str)) {
      const char* kMemberName = "inner";

      // This is a non-struct or a struct that is nested somewhere else, so we
      // need to wrap it first.
      auto* wrapper = utils::GetOrCreate(wrapper_structs, ty, [&]() {
        auto* block =
            ctx.dst->ASTNodes().Create<SpirvBlockDecoration>(ctx.dst->ID());
        auto wrapper_name = ctx.src->Symbols().NameFor(var->symbol) + "_block";
        auto* ret = ctx.dst->create<ast::Struct>(
            ctx.dst->Symbols().New(wrapper_name),
            ast::StructMemberList{
                ctx.dst->Member(kMemberName, CreateASTTypeFor(ctx, ty))},
            ast::DecorationList{block});
        ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), var, ret);
        return ret;
      });
      ctx.Replace(var->type, ctx.dst->ty.Of(wrapper));

      // Insert a member accessor to get the original type from the wrapper at
      // any usage of the original variable.
      for (auto* user : sem_var->Users()) {
        ctx.Replace(
            user->Declaration(),
            ctx.dst->MemberAccessor(ctx.Clone(var->symbol), kMemberName));
      }
    } else {
      // Add a block decoration to this struct directly.
      auto* block =
          ctx.dst->ASTNodes().Create<SpirvBlockDecoration>(ctx.dst->ID());
      ctx.InsertFront(str->Declaration()->decorations, block);
    }
  }

  ctx.Clone();
}

AddSpirvBlockDecoration::SpirvBlockDecoration::SpirvBlockDecoration(
    ProgramID pid)
    : Base(pid) {}
AddSpirvBlockDecoration::SpirvBlockDecoration::~SpirvBlockDecoration() =
    default;
std::string AddSpirvBlockDecoration::SpirvBlockDecoration::InternalName()
    const {
  return "spirv_block";
}

const AddSpirvBlockDecoration::SpirvBlockDecoration*
AddSpirvBlockDecoration::SpirvBlockDecoration::Clone(CloneContext* ctx) const {
  return ctx->dst->ASTNodes()
      .Create<AddSpirvBlockDecoration::SpirvBlockDecoration>(ctx->dst->ID());
}

}  // namespace transform
}  // namespace tint
