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

#include <string>
#include <unordered_set>
#include <utility>

#include "src/tint/ast/disable_validation_attribute.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/function.h"
#include "src/tint/sem/variable.h"
#include "src/tint/utils/string.h"

TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper);
TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper::Remappings);

namespace tint::transform {

BindingRemapper::Remappings::Remappings(BindingPoints bp, AccessControls ac, bool may_collide)
    : binding_points(std::move(bp)),
      access_controls(std::move(ac)),
      allow_collisions(may_collide) {}

BindingRemapper::Remappings::Remappings(const Remappings&) = default;
BindingRemapper::Remappings::~Remappings() = default;

BindingRemapper::BindingRemapper() = default;
BindingRemapper::~BindingRemapper() = default;

bool BindingRemapper::ShouldRun(const Program*, const DataMap& inputs) const {
    if (auto* remappings = inputs.Get<Remappings>()) {
        return !remappings->binding_points.empty() || !remappings->access_controls.empty();
    }
    return false;
}

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

    // A set of post-remapped binding points that need to be decorated with a
    // DisableValidationAttribute to disable binding-point-collision validation
    std::unordered_set<sem::BindingPoint> add_collision_attr;

    if (remappings->allow_collisions) {
        // Scan for binding point collisions generated by this transform.
        // Populate all collisions in the `add_collision_attr` set.
        for (auto* func_ast : ctx.src->AST().Functions()) {
            if (!func_ast->IsEntryPoint()) {
                continue;
            }
            auto* func = ctx.src->Sem().Get(func_ast);
            std::unordered_map<sem::BindingPoint, int> binding_point_counts;
            for (auto* global : func->TransitivelyReferencedGlobals()) {
                if (global->Declaration()->HasBindingPoint()) {
                    BindingPoint from = global->BindingPoint();

                    auto bp_it = remappings->binding_points.find(from);
                    if (bp_it != remappings->binding_points.end()) {
                        // Remapped
                        BindingPoint to = bp_it->second;
                        if (binding_point_counts[to]++) {
                            add_collision_attr.emplace(to);
                        }
                    } else {
                        // No remapping
                        if (binding_point_counts[from]++) {
                            add_collision_attr.emplace(from);
                        }
                    }
                }
            }
        }
    }

    for (auto* var : ctx.src->AST().Globals<ast::Var>()) {
        if (var->HasBindingPoint()) {
            auto* global_sem = ctx.src->Sem().Get<sem::GlobalVariable>(var);

            // The original binding point
            BindingPoint from = global_sem->BindingPoint();

            // The binding point after remapping
            BindingPoint bp = from;

            // Replace any group or binding attributes.
            // Note: This has to be performed *before* remapping access controls, as
            // `ctx.Clone(var->attributes)` depend on these replacements.
            auto bp_it = remappings->binding_points.find(from);
            if (bp_it != remappings->binding_points.end()) {
                BindingPoint to = bp_it->second;
                auto* new_group = ctx.dst->Group(AInt(to.group));
                auto* new_binding = ctx.dst->Binding(AInt(to.binding));

                auto* old_group = ast::GetAttribute<ast::GroupAttribute>(var->attributes);
                auto* old_binding = ast::GetAttribute<ast::BindingAttribute>(var->attributes);

                ctx.Replace(old_group, new_group);
                ctx.Replace(old_binding, new_binding);
                bp = to;
            }

            // Replace any access controls.
            auto ac_it = remappings->access_controls.find(from);
            if (ac_it != remappings->access_controls.end()) {
                ast::Access ac = ac_it->second;
                if (ac == ast::Access::kInvalid) {
                    ctx.dst->Diagnostics().add_error(
                        diag::System::Transform,
                        "invalid access mode (" + std::to_string(static_cast<uint32_t>(ac)) + ")");
                    return;
                }
                auto* sem = ctx.src->Sem().Get(var);
                if (sem->AddressSpace() != ast::AddressSpace::kStorage) {
                    ctx.dst->Diagnostics().add_error(
                        diag::System::Transform,
                        "cannot apply access control to variable with address space " +
                            std::string(utils::ToString(sem->AddressSpace())));
                    return;
                }
                auto* ty = sem->Type()->UnwrapRef();
                const ast::Type* inner_ty = CreateASTTypeFor(ctx, ty);
                auto* new_var =
                    ctx.dst->Var(ctx.Clone(var->source), ctx.Clone(var->symbol), inner_ty,
                                 var->declared_address_space, ac, ctx.Clone(var->constructor),
                                 ctx.Clone(var->attributes));
                ctx.Replace(var, new_var);
            }

            // Add `DisableValidationAttribute`s if required
            if (add_collision_attr.count(bp)) {
                auto* attribute = ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision);
                ctx.InsertBefore(var->attributes, *var->attributes.begin(), attribute);
            }
        }
    }

    ctx.Clone();
}

}  // namespace tint::transform
