// 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/fuzzers/tint_ast_fuzzer/mutations/replace_identifier.h"

#include <utility>

#include "src/tint/fuzzers/tint_ast_fuzzer/util.h"
#include "src/tint/program_builder.h"

namespace tint::fuzzers::ast_fuzzer {

MutationReplaceIdentifier::MutationReplaceIdentifier(
    protobufs::MutationReplaceIdentifier message)
    : message_(std::move(message)) {}

MutationReplaceIdentifier::MutationReplaceIdentifier(uint32_t use_id,
                                                     uint32_t replacement_id) {
  message_.set_use_id(use_id);
  message_.set_replacement_id(replacement_id);
}

bool MutationReplaceIdentifier::IsApplicable(
    const tint::Program& program,
    const NodeIdMap& node_id_map) const {
  const auto* use_ast_node = tint::As<ast::IdentifierExpression>(
      node_id_map.GetNode(message_.use_id()));
  if (!use_ast_node) {
    // Either the `use_id` is invalid or the node is not an
    // `IdentifierExpression`.
    return false;
  }

  const auto* use_sem_node =
      tint::As<sem::VariableUser>(program.Sem().Get(use_ast_node));
  if (!use_sem_node) {
    // Either the semantic information is not present for a `use_node` or that
    // node is not a variable user.
    return false;
  }

  const auto* replacement_ast_node =
      tint::As<ast::Variable>(node_id_map.GetNode(message_.replacement_id()));
  if (!replacement_ast_node) {
    // Either the `replacement_id` is invalid or is not an id of a variable.
    return false;
  }

  const auto* replacement_sem_node = program.Sem().Get(replacement_ast_node);
  if (!replacement_sem_node) {
    return false;
  }

  if (replacement_sem_node == use_sem_node->Variable()) {
    return false;
  }

  auto in_scope =
      util::GetAllVarsInScope(program, use_sem_node->Stmt(),
                              [replacement_sem_node](const sem::Variable* var) {
                                return var == replacement_sem_node;
                              });
  if (in_scope.empty()) {
    // The replacement variable is not in scope.
    return false;
  }

  return use_sem_node->Type() == replacement_sem_node->Type();
}

void MutationReplaceIdentifier::Apply(const NodeIdMap& node_id_map,
                                      tint::CloneContext* clone_context,
                                      NodeIdMap* new_node_id_map) const {
  const auto* use_node = node_id_map.GetNode(message_.use_id());
  const auto* replacement_var =
      tint::As<ast::Variable>(node_id_map.GetNode(message_.replacement_id()));

  auto* cloned_replacement =
      clone_context->dst->Expr(clone_context->Clone(use_node->source),
                               clone_context->Clone(replacement_var->symbol));
  clone_context->Replace(use_node, cloned_replacement);
  new_node_id_map->Add(cloned_replacement, message_.use_id());
}

protobufs::Mutation MutationReplaceIdentifier::ToMessage() const {
  protobufs::Mutation mutation;
  *mutation.mutable_replace_identifier() = message_;
  return mutation;
}

}  // namespace tint::fuzzers::ast_fuzzer
