// Copyright 2023 Google LLC
//
// 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
//
//     https://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 "mpact/sim/decoder/proto_instruction_encoding.h"

#include <algorithm>
#include <functional>
#include <string>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/decoder/format_name.h"
#include "mpact/sim/decoder/proto_constraint_expression.h"
#include "mpact/sim/decoder/proto_format_contexts.h"
#include "src/google/protobuf/descriptor.h"

namespace mpact {
namespace sim {
namespace decoder {
namespace proto_fmt {

using mpact::sim::machine_description::instruction_set::ToPascalCase;

ProtoInstructionEncoding::ProtoInstructionEncoding(
    std::string name, ProtoInstructionGroup* parent)
    : name_(name), instruction_group_(parent) {}

// Copy constructor.
ProtoInstructionEncoding::ProtoInstructionEncoding(
    const ProtoInstructionEncoding& rhs) {
  name_ = rhs.name_;
  instruction_group_ = rhs.instruction_group_;
  setter_code_ = rhs.setter_code_;
  for (const auto& [name, setter_ptr] : rhs.setter_map_) {
    setter_map_.insert({name, new ProtoSetter(*setter_ptr)});
  }
  for (const auto* constraint : rhs.equal_constraints_) {
    equal_constraints_.push_back(new ProtoConstraint(*constraint));
  }
  for (const auto* constraint : rhs.other_constraints_) {
    other_constraints_.push_back(new ProtoConstraint(*constraint));
  }
  for (const auto& [name, constraint_ptr] : rhs.has_constraints_) {
    has_constraints_.insert({name, new ProtoConstraint(*constraint_ptr)});
  }
}

ProtoInstructionEncoding::~ProtoInstructionEncoding() {
  for (const auto* constraint : equal_constraints_) {
    delete constraint->expr;
    delete constraint;
  }
  equal_constraints_.clear();
  for (const auto* constraint : other_constraints_) {
    delete constraint->expr;
    delete constraint;
  }
  other_constraints_.clear();
  for (const auto& [unused, constraint] : has_constraints_) {
    delete constraint;
  }
  has_constraints_.clear();
  for (const auto& [unused, setter] : setter_map_) {
    delete setter;
  }
  setter_map_.clear();
}

absl::Status ProtoInstructionEncoding::AddSetter(
    SetterDefCtx* ctx, const std::string& name,
    const google::protobuf::FieldDescriptor* field_descriptor,
    const std::vector<const google::protobuf::FieldDescriptor*>& one_of_fields,
    IfNotCtx* if_not) {
  if (ctx == nullptr) return absl::InvalidArgumentError("Context is null");

  // If there is a setter already for that name, return an error.
  auto iter = setter_map_.find(name);
  if (iter != setter_map_.end()) {
    return absl::AlreadyExistsError(
        absl::StrCat("Setter '", name, "' already defined."));
  }
  // Setters are added after constraints. For each depends_on, see if the
  // constraint already exists for the encoding. If so, remove it from the
  // one_of_fields vector, as it is guaranteed to be satisfied if the
  // instruction is successfully decoded. If it contradicts an existing
  // constraint, signal an error.
  ProtoConstraint* depends_on = nullptr;
  for (auto const* desc : one_of_fields) {
    auto iter = oneof_field_map_.find(desc->containing_oneof());
    if (iter != oneof_field_map_.end()) {
      // Duplicate of an encoding constraint.
      if (iter->second == desc) continue;
      // Conflict.
      return absl::InternalError(absl::StrCat(
          "One_of constraint on '", desc->name(),
          "' contradicts encoding constraint on '", iter->second->name(), "'"));
    }
    depends_on = AddHasConstraint(desc, depends_on);
  }

  // Add the setter information.
  setter_map_.emplace(
      name, new ProtoSetter{ctx, name, field_descriptor, if_not, depends_on});
  return absl::OkStatus();
}

absl::Status ProtoInstructionEncoding::AddConstraint(
    FieldConstraintCtx* ctx, ConstraintType op,
    const google::protobuf::FieldDescriptor* field_descriptor,
    const std::vector<const google::protobuf::FieldDescriptor*>& one_of_fields,
    const ProtoConstraintExpression* expr) {
  // One_of_fields is a list of fields that have 'kHas' constraints that are
  // prerequisites for the constraint being added. The variable depends_on
  // points to the end of the dependence chain, or nullptr if there are no or
  // duplicate one_of field constraints.
  ProtoConstraint* depends_on = nullptr;
  for (auto const* desc : one_of_fields) {
    auto iter = oneof_field_map_.find(desc->containing_oneof());
    if (iter != oneof_field_map_.end()) {
      if (iter->second == field_descriptor) {
        continue;  // Ignore duplicate.
      } else {
        // This contradicts a previous one_of constraint. Flag an error.
        return absl::InternalError(
            absl::StrCat("One_of constraint on '", desc->name(),
                         "' contradicts previous constraint on '",
                         iter->second->name(), "'"));
      }
    }
    // Add the one_of to the oneof_field_map_.
    oneof_field_map_.emplace(desc->containing_oneof(), desc);
    depends_on = AddHasConstraint(desc, depends_on);
  }
  // In order to generate a reasonably efficient decoder we divide the
  // constraints into two sets, those that can be used as indices into function
  // call tables or used as values in switch statements to differentiate between
  // the most instructions, and those that have to be evaluated in a slower
  // (often serial) manner. Only constraints on fields that don't depend on
  // other one_of fields can be treated in this manner. A dependency on one_of
  // fields can be used to create additional constraints, of which one is at the
  // top level in the proto.

  if (!one_of_fields.empty()) {
    // Add equal constraint on the first one_of_field dependency.
    equal_constraints_.push_back(new ProtoConstraint{
        ctx, one_of_fields[0], ConstraintType::kHas, nullptr, 0, nullptr});
    // Add the remaining one_of depende ncies to the other constraints.
    for (int i = 1; i < one_of_fields.size(); ++i) {
      other_constraints_.push_back(new ProtoConstraint{
          ctx, one_of_fields[i], ConstraintType::kHas, nullptr, 0, nullptr});
      // Add the constraint to the 'other' constraints.
      other_constraints_.push_back(
          new ProtoConstraint{ctx, field_descriptor, op, expr, 0, depends_on});
    }
    return absl::OkStatus();
  }

  // A kHas constraint on a member of a one_of field is equivalent to an kEq
  // constraint on the value of the one_of '_value()' function, so add it to the
  // equal_constraints vector. For kEq constraints, if the type of the field is
  // not an integer type, put it in the other_constraints.

  if ((op == ConstraintType::kEq) &&
      (IsIntType(kCppToVariantTypeMap[field_descriptor->cpp_type()]))) {
    // If it's an equal constraint with an integer type, add it to the 'equal'
    // constraints.
    equal_constraints_.push_back(
        new ProtoConstraint{ctx, field_descriptor, op, expr, 0, nullptr});
  } else if ((op == ConstraintType::kHas) &&
             (field_descriptor->containing_oneof() != nullptr)) {
    // If it's a kHas constraint on an one_of field, first make sure that it
    // does not contradict or duplicate any previous one_of kHas constraints.
    auto* oneof_desc = field_descriptor->containing_oneof();
    auto iter = oneof_field_map_.find(oneof_desc);
    if (iter != oneof_field_map_.end()) {
      // There is already a constraint on this oneof. Either it's the same
      // constraint, which means we can ignore this one, or it is for a
      // different field in which case it is a contradiction. Either way, the
      // constraint does not get added.
      if (iter->second == field_descriptor) {
        // It is a duplicate constraint. just ignore.
        return absl::OkStatus();
      }
      // It is a different field of the one_of, so there is a contradiction.
      // Return an error.
      return absl::InternalError(absl::StrCat(
          "One_of constraint on '", field_descriptor->name(),
          "' contradicts previous constraint on '", iter->second->name(), "'"));
    }
    oneof_field_map_.emplace(oneof_desc, field_descriptor);
    equal_constraints_.push_back(
        new ProtoConstraint{ctx, field_descriptor, op, nullptr, 0, nullptr});
  } else {
    // Otherwise add it to the 'other' constraints.
    other_constraints_.push_back(
        new ProtoConstraint{ctx, field_descriptor, op, expr, 0, nullptr});
  }
  return absl::OkStatus();
}

ProtoConstraint* ProtoInstructionEncoding::AddHasConstraint(
    const google::protobuf::FieldDescriptor* field_descriptor,
    ProtoConstraint* depends_on) {
  if (depends_on != nullptr) {
    if (!has_constraints_.contains(depends_on->field_descriptor->full_name())) {
      return nullptr;
    }
  }
  auto iter = has_constraints_.find(field_descriptor->full_name());
  if (iter != has_constraints_.end()) return iter->second;

  ProtoConstraint* constraint = new ProtoConstraint{
      nullptr, field_descriptor, ConstraintType::kHas, nullptr, 0, depends_on};
  has_constraints_.emplace(field_descriptor->full_name(), constraint);
  return constraint;
}

// This function returns a string with properly indented C++ code for the
// setters for this instruction. The '$' is used instead of the message name.
void ProtoInstructionEncoding::GenerateSetterCode() {
  const int kIndent = 0;
  if (setter_map_.empty()) return;
  absl::StrAppend(&setter_code_, "/* setters for ", name(), " */\n");
  // First need to group setters by dependencies on fields, split into setters
  // with if_not and those without (except for those with no depends_on.).
  // Also need to group constraints by their dependencies. Use multimap that
  // maps from a constraint to those that depend on it.
  absl::btree_multimap<const ProtoConstraint*, const ProtoConstraint*>
      grouped_constraints;
  // Maintain a set of inserted constraints, so that the multimap has no
  // duplicate key-value pairs.
  absl::flat_hash_set<const ProtoConstraint*> inserted_constraints;
  // This set contains the top level constraints that do not depend on any
  // other constraints, and thus are the beginning of the 'dependence chains'.
  absl::flat_hash_set<const ProtoConstraint*> constraint_tops;
  // These multimaps map from a constraint to the set of setters dependent on
  // that constraint.
  absl::btree_multimap<const ProtoConstraint*, const ProtoSetter*>
      grouped_setters;
  absl::btree_multimap<const ProtoConstraint*, const ProtoSetter*>
      grouped_if_not_setters;

  // Lambda used to determine if a constraint is already satisfied by
  // an identical constraint used in the decoding of the instruction.
  auto is_in_eq_constraints = [&](const ProtoConstraint* constraint) {
    auto* field_descriptor = constraint->field_descriptor;
    auto iter = std::find_if(
        equal_constraints_.begin(), equal_constraints_.end(),
        [&field_descriptor](const ProtoConstraint* constraint) {
          return (constraint->op == ConstraintType::kHas) &&
                 (constraint->field_descriptor == field_descriptor);
        });
    return (iter != equal_constraints_.end());
  };

  // First build up the data structures.
  // Iterate over the setters for this instruction.
  for (auto& [name, setter_ptr] : setter_map_) {
    // Get any one_of dependency that the setter depends on.
    auto* depends = setter_ptr->depends_on;
    // If the dependency matches one in the equal constraints for decoding the
    // instruction, it will be true for the setters, and does not have to be
    // tested for again.
    if (depends != nullptr && is_in_eq_constraints(depends)) depends = nullptr;

    // Group the setter in a multimap that maps from a constraint to a
    // dependent constraint. There are two sets, depending on whether the setter
    // has an if_not clause or not. Setters with null dependency are inserted in
    // the regular group regardless of if_not value.
    if (depends != nullptr && setter_ptr->if_not != nullptr) {
      grouped_if_not_setters.emplace(depends, setter_ptr);
    } else {
      grouped_setters.emplace(depends, setter_ptr);
    }
    // If there is no one_of dependency, or the setter has an if_not,
    // go to the next setter.
    if (depends == nullptr) continue;
    if (setter_ptr->if_not != nullptr) continue;

    // Add dependency 'links' to the grouped_constraints map, that map
    // from a constraint to the constraints that depend on it.
    while (depends != nullptr && depends->depends_on != nullptr) {
      // See if 'depends' has been inserted yet, if not, add a map entry from
      // the one_of it depends on to it in the grouped_constraints multi map.
      auto [unused, inserted] = inserted_constraints.insert(depends);
      if (inserted) {
        grouped_constraints.emplace(depends->depends_on, depends);
      }
      // Go to the next dependency in the chain, but make sure to skip any
      // that are satisfied by the equal constraints.
      depends = depends->depends_on;
    }
    // Maintain a set of the the top level constraints (which do not depend
    // on other constraints).
    constraint_tops.insert(depends);
  }

  // Helper lambda functions used in the loop nest below.
  // This generates the assignment.
  auto assign = [&](int indent, const ProtoSetter* setter) {
    absl::StrAppend(&setter_code_, std::string(indent, ' '), "decoder->Set",
                    ToPascalCase(setter->name), "($.");
    auto field_name = setter->ctx->qualified_ident()->getText();
    // Need to convert from a.b.c to a().b().c().
    auto call =
        absl::StrCat(absl::StrReplaceAll(field_name, {{".", "()."}}), "()");
    if (setter->if_not == nullptr) {
      absl::StrAppend(&setter_code_, call, "); // ",
                      setter->field_descriptor->full_name(), "\n");
    } else {
      auto pos = call.find_last_of('.');
      std::string name;
      if (pos != std::string::npos) {
        std::string prefix = call.substr(0, pos + 1);
        name = prefix + "has_" + call.substr(pos + 1);
      } else {
        name = "has_" + call;
      }
      std::string txt = setter->if_not->value() != nullptr
                            ? setter->if_not->value()->getText()
                            : setter->if_not->qualified_ident()->getText();
      absl::StrAppend(&setter_code_, name, " ? $.", call, " : ", txt, ");\n");
    }
  };

  // First process the setters with no oneof dependencies.
  auto [begin, end] = grouped_setters.equal_range(nullptr);
  for (auto iter = begin; iter != end; ++iter) assign(kIndent, iter->second);

  // Helper lambda function to generate the if statement to guard individual
  // setters.
  auto generate_if_statement = [&](int indent,
                                   const ProtoConstraint* constraint) {
    auto* desc = constraint->field_descriptor;
    auto* oneof = desc->containing_oneof();
    absl::StrAppend(&setter_code_, std::string(indent, ' '), "if ($.");
    if (oneof != nullptr) {
      absl::StrAppend(&setter_code_, oneof->name(),
                      "_case() == ", ToPascalCase(oneof->name()), "Case::k",
                      ToPascalCase(desc->name()), ") {\n");
    } else {
      absl::StrAppend(&setter_code_, "has_", desc->name(), ") {\n");
    }
  };

  // Recursive lambda for generating nested if statements around groups of
  // setters with the same constraint.
  std::function<void(int, const ProtoConstraint*)> generate_nested_ifs =
      [&](int indent, const ProtoConstraint* constraint) {
        // Generate if statement for 'constraint'.
        generate_if_statement(indent, constraint);
        indent += 2;
        // Perform all the assigns that depend on constraint.
        {
          auto [begin, end] = grouped_setters.equal_range(constraint);
          for (auto iter = begin; iter != end; ++iter)
            assign(indent, iter->second);
        }
        // Generate any ifs for constraints dependent on the current constraint.
        {
          auto [begin, end] = grouped_constraints.equal_range(constraint);
          for (auto iter = begin; iter != end; ++iter) {
            generate_nested_ifs(indent, iter->second);
          }
        }
        indent -= 2;
        absl::StrAppend(&setter_code_, std::string(indent, ' '), "}\n");
      };

  // Process the setters with no if_not's.
  for (auto* constraint : constraint_tops) {
    generate_nested_ifs(kIndent, constraint);
  }

  // Recursive lambda for generating the conditions of the if statements used
  // by setters with 'if_not' constructs.
  std::function<void(const ProtoConstraint*, std::string&)>
      recursive_if_conditions =
          [&](const ProtoConstraint* constraint, std::string& if_conditions) {
            auto* desc = constraint->field_descriptor;
            auto* depends_on = constraint->depends_on;
            std::string sep = "";
            // Generate the conditions in reverse order of the depends_on list.
            if (depends_on != nullptr) {
              recursive_if_conditions(depends_on, if_conditions);
              if (!if_conditions.empty()) sep = " && ";
            }
            auto* oneof = desc->containing_oneof();
            std::string ident = constraint->ctx->qualified_ident()->getText();
            auto pos = ident.find_last_of('.');
            std::string prefix;
            if (pos != std::string::npos) {
              prefix = ident.substr(0, pos + 1);
            }
            if (!prefix.empty()) {
              // Convert a.b.c to a().b().c().
              prefix = absl::StrReplaceAll(prefix, {{".", "()."}});
            }
            if (oneof != nullptr) {
              absl::StrAppend(&if_conditions, sep, "($.", prefix, oneof->name(),
                              "_case() == k", ToPascalCase(desc->name()), ")");
            } else {
              absl::StrAppend(&if_conditions, sep, "($.", prefix, "has_",
                              desc->name(), ")");
            }
          };

  // Process the setters with dependencies and if_not's.
  for (auto iter = grouped_if_not_setters.begin();
       iter != grouped_if_not_setters.end();
       /*empty increment expression - it's done inside nested loop below*/) {
    std::string if_conditions;
    recursive_if_conditions(iter->first, if_conditions);
    absl::StrAppend(&setter_code_, std::string(kIndent, ' '), "if (",
                    if_conditions, ") {\n");
    auto count = grouped_if_not_setters.count(iter->first);
    for (auto i = 0; i < count; ++i) {
      assign(kIndent + 2, iter->second);
      ++iter;
    }
    absl::StrAppend(&setter_code_, std::string(kIndent, ' '), "}\n");
  }
}

std::string ProtoInstructionEncoding::GetSetterCode(
    absl::string_view message_name, int indent) const {
  return absl::StrReplaceAll(
      setter_code_,
      {{"$", message_name}, {"\n", "\n" + std::string(indent, ' ')}});
}

}  // namespace proto_fmt
}  // namespace decoder
}  // namespace sim
}  // namespace mpact
