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

#include <cassert>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "fuzzers/tint_ast_fuzzer/mutation_finders/replace_identifiers.h"
#include "fuzzers/tint_ast_fuzzer/node_id_map.h"

#include "src/program_builder.h"

namespace tint {
namespace fuzzers {
namespace ast_fuzzer {
namespace {

template <typename T, typename... Args>
void MaybeAddFinder(bool enable_all_mutations,
                    ProbabilityContext* probability_context,
                    MutationFinderList* finders,
                    Args&&... args) {
  if (enable_all_mutations || probability_context->RandomBool()) {
    finders->push_back(std::make_unique<T>(std::forward<Args>(args)...));
  }
}

MutationFinderList CreateMutationFinders(
    ProbabilityContext* probability_context,
    bool enable_all_mutations) {
  MutationFinderList result;
  do {
    MaybeAddFinder<MutationFinderReplaceIdentifiers>(
        enable_all_mutations, probability_context, &result);
  } while (result.empty());
  return result;
}

}  // namespace

bool MaybeApplyMutation(const tint::Program& program,
                        const Mutation& mutation,
                        const NodeIdMap& node_id_map,
                        tint::Program* out_program,
                        NodeIdMap* out_node_id_map,
                        protobufs::MutationSequence* mutation_sequence) {
  assert(out_program && "`out_program` may not be a nullptr");
  assert(out_node_id_map && "`out_node_id_map` may not be a nullptr");

  if (!mutation.IsApplicable(program, node_id_map)) {
    return false;
  }

  // The mutated `program` will be copied into the `mutated` program builder.
  tint::ProgramBuilder mutated;
  tint::CloneContext clone_context(&mutated, &program);
  NodeIdMap new_node_id_map;
  clone_context.ReplaceAll(
      [&node_id_map, &new_node_id_map, &clone_context](ast::Node* node) {
        // Make sure all `tint::ast::` nodes' ids are preserved.
        auto* cloned = tint::As<ast::Node>(node->Clone(&clone_context));
        new_node_id_map.Add(cloned, node_id_map.GetId(node));
        return cloned;
      });

  mutation.Apply(node_id_map, &clone_context, &new_node_id_map);
  if (mutation_sequence) {
    *mutation_sequence->add_mutation() = mutation.ToMessage();
  }

  clone_context.Clone();
  *out_program = tint::Program(std::move(mutated));
  *out_node_id_map = std::move(new_node_id_map);
  return true;
}

tint::Program Replay(tint::Program program,
                     const protobufs::MutationSequence& mutation_sequence) {
  assert(program.IsValid() && "Initial program is invalid");

  NodeIdMap node_id_map(program);
  for (const auto& mutation_message : mutation_sequence.mutation()) {
    auto mutation = Mutation::FromMessage(mutation_message);
    auto status = MaybeApplyMutation(program, *mutation, node_id_map, &program,
                                     &node_id_map, nullptr);
    (void)status;  // `status` will be unused in release mode.
    assert(status && "`mutation` is inapplicable - it's most likely a bug");
    if (!program.IsValid()) {
      // `mutation` has a bug.
      break;
    }
  }

  return program;
}

tint::Program Mutate(tint::Program program,
                     ProbabilityContext* probability_context,
                     bool enable_all_mutations,
                     uint32_t max_applied_mutations,
                     protobufs::MutationSequence* mutation_sequence) {
  assert(max_applied_mutations != 0 &&
         "Maximum number of mutations is invalid");
  assert(program.IsValid() && "Initial program is invalid");

  // The number of allowed failed attempts to apply mutations. If this number is
  // exceeded, the mutator is considered stuck and the mutation session is
  // stopped.
  const uint32_t kMaxFailureToApply = 10;

  auto finders =
      CreateMutationFinders(probability_context, enable_all_mutations);
  NodeIdMap node_id_map(program);

  // Total number of applied mutations during this call to `Mutate`.
  uint32_t applied_mutations = 0;

  // The number of consecutively failed attempts to apply mutations.
  uint32_t failure_to_apply = 0;

  // Apply mutations as long as the `program` is valid, the limit on the number
  // of mutations is not reached and the mutator is not stuck (i.e. unable to
  // apply any mutations for some time).
  while (program.IsValid() && applied_mutations < max_applied_mutations &&
         failure_to_apply < kMaxFailureToApply) {
    // Get all applicable mutations from some mutation finder.
    const auto& mutation_finder =
        finders[probability_context->GetRandomIndex(finders)];
    auto mutations = mutation_finder->FindMutations(program, node_id_map,
                                                    probability_context);

    const auto old_applied_mutations = applied_mutations;
    for (const auto& mutation : mutations) {
      if (!probability_context->ChoosePercentage(
              mutation_finder->GetChanceOfApplyingMutation(
                  probability_context))) {
        // Skip this `mutation` probabilistically.
        continue;
      }

      if (!MaybeApplyMutation(program, *mutation, node_id_map, &program,
                              &node_id_map, mutation_sequence)) {
        // This `mutation` is inapplicable. This may happen if some of the
        // earlier mutations cancelled this one.
        continue;
      }

      applied_mutations++;
      if (!program.IsValid()) {
        // This `mutation` has a bug.
        return program;
      }
    }

    if (old_applied_mutations == applied_mutations) {
      // No mutation was applied. Increase the counter to prevent an infinite
      // loop.
      failure_to_apply++;
    } else {
      failure_to_apply = 0;
    }
  }

  return program;
}

}  // namespace ast_fuzzer
}  // namespace fuzzers
}  // namespace tint
