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

#include <utility>
#include <vector>

#include "src/tint/program_builder.h"

namespace tint::fuzzers::ast_fuzzer {

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

MutationWrapUnaryOperator::MutationWrapUnaryOperator(
    uint32_t expression_id,
    uint32_t fresh_id,
    ast::UnaryOp unary_op_wrapper) {
  message_.set_expression_id(expression_id);
  message_.set_fresh_id(fresh_id);
  message_.set_unary_op_wrapper(static_cast<uint32_t>(unary_op_wrapper));
}

bool MutationWrapUnaryOperator::IsApplicable(
    const tint::Program& program,
    const NodeIdMap& node_id_map) const {
  // Check if id that will be assigned is fresh.
  if (!node_id_map.IdIsFreshAndValid(message_.fresh_id())) {
    return false;
  }

  const auto* expression_ast_node =
      tint::As<ast::Expression>(node_id_map.GetNode(message_.expression_id()));

  if (!expression_ast_node) {
    // Either the node is not present with the given id or
    // the node is not a valid expression type.
    return false;
  }

  const auto* expression_sem_node =
      tint::As<sem::Expression>(program.Sem().Get(expression_ast_node));

  if (!expression_sem_node) {
    // Semantic information for the expression ast node is not present
    // or the semantic node is not a valid expression type node.
    return false;
  }

  ast::UnaryOp unary_op_wrapper =
      static_cast<ast::UnaryOp>(message_.unary_op_wrapper());

  std::vector<ast::UnaryOp> valid_ops =
      GetValidUnaryWrapper(*expression_sem_node);

  // There is no available unary operator or |unary_op_wrapper| is a
  // type that is not allowed for the given expression.
  if (std::find(valid_ops.begin(), valid_ops.end(), unary_op_wrapper) ==
      valid_ops.end()) {
    return false;
  }

  return true;
}

void MutationWrapUnaryOperator::Apply(const NodeIdMap& node_id_map,
                                      tint::CloneContext* clone_context,
                                      NodeIdMap* new_node_id_map) const {
  auto* expression_node =
      tint::As<ast::Expression>(node_id_map.GetNode(message_.expression_id()));

  auto* replacement_expression_node =
      clone_context->dst->create<ast::UnaryOpExpression>(
          static_cast<ast::UnaryOp>(message_.unary_op_wrapper()),
          clone_context->Clone(expression_node));

  clone_context->Replace(expression_node, replacement_expression_node);

  new_node_id_map->Add(replacement_expression_node, message_.fresh_id());
}

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

std::vector<ast::UnaryOp> MutationWrapUnaryOperator::GetValidUnaryWrapper(
    const sem::Expression& expr) {
  const auto* expr_type = expr.Type();
  if (expr_type->is_bool_scalar_or_vector()) {
    return {ast::UnaryOp::kNot};
  }

  if (expr_type->is_signed_scalar_or_vector()) {
    return {ast::UnaryOp::kNegation, ast::UnaryOp::kComplement};
  }

  if (expr_type->is_unsigned_scalar_or_vector()) {
    return {ast::UnaryOp::kComplement};
  }

  if (expr_type->is_float_scalar_or_vector()) {
    return {ast::UnaryOp::kNegation};
  }

  return {};
}

}  // namespace tint::fuzzers::ast_fuzzer
