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

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <string>
#include <vector>

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

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

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

struct FieldInfo {
  const google::protobuf::FieldDescriptor* field;
  const google::protobuf::OneofDescriptor* oneof;
  QualifiedIdentCtx* ctx;
  absl::btree_multimap<int64_t, const ProtoInstructionEncoding*> value_map;
  int64_t min_value = 0;
  int64_t max_value = 0;
  size_t unique_values = 0;
  double density = 0.0;
};

using ConstraintValueRange = ProtoConstraintValueSet::SubRange;

ProtoEncodingGroup::ProtoEncodingGroup(ProtoInstructionGroup* inst_group,
                                       int level,
                                       DecoderErrorListener* error_listener)
    : ProtoEncodingGroup(nullptr, inst_group, level, error_listener) {}

ProtoEncodingGroup::ProtoEncodingGroup(ProtoEncodingGroup* parent,
                                       ProtoInstructionGroup* inst_group,
                                       int level,
                                       DecoderErrorListener* error_listener)
    : inst_group_(inst_group),
      parent_(parent),
      error_listener_(error_listener),
      level_(level) {}

ProtoEncodingGroup::~ProtoEncodingGroup() {
  for (auto const& [unused, field_info] : field_map_) {
    delete field_info;
  }
  field_map_.clear();
  for (auto const* enc : encoding_vec_) {
    delete enc;
  }
  encoding_vec_.clear();
  inst_group_ = nullptr;
  for (auto const* enc_group : encoding_group_vec_) {
    delete enc_group;
  }
  encoding_group_vec_.clear();
}

void ProtoEncodingGroup::AddEncoding(ProtoInstructionEncoding* enc) {
  // All constraints in equal_constraints are kEq constraints on integer
  // fields, or are kHas constraints which are kEq constraints on the
  // '_value()' function of the one_of field (which is an int value).
  // The first step is to determine which constraints differentiate the most
  // instructions in the encoding group.
  for (auto* eq_constraint : enc->equal_constraints()) {
    auto const* field = eq_constraint->field_descriptor;
    auto const* oneof = field->containing_oneof();
    auto const* expr = eq_constraint->expr;
    auto op = eq_constraint->op;
    auto* qualifed_ident_ctx = eq_constraint->ctx->qualified_ident();
    int64_t value;  // Store the value in an int64_t.
    if (op == ConstraintType::kEq) {
      switch (expr->variant_type()) {
        case *ProtoValueIndex::kInt32:
          value = expr->GetValueAs<int32_t>();
          break;
        case *ProtoValueIndex::kInt64:
          value = expr->GetValueAs<int64_t>();
          break;
        case *ProtoValueIndex::kUint32:
          value = expr->GetValueAs<uint32_t>();
          break;
        case *ProtoValueIndex::kUint64: {
          // If the value overflows int64_t, just flag an error. Keep it
          // simple.
          uint64_t tmp = expr->GetValueAs<uint64_t>();
          if (tmp > std::numeric_limits<int64_t>::max()) {
            error_listener()->semanticError(
                eq_constraint->ctx->start,
                absl::StrCat("Expression value for field '", field->name(),
                             "' overflows int64_t."));
            return;
          }
          value = static_cast<int64_t>(tmp);
          break;
        }
        default:
          error_listener()->semanticError(
              eq_constraint->ctx->start,
              absl::StrCat(
                  "Illegal type in expression in constraint for field '",
                  field->name(), "'."));
          return;
      }
      oneof = nullptr;
    } else if (op == ConstraintType::kHas) {
      value = field->index();
      oneof = field->containing_oneof();
      field = nullptr;
    } else {
      error_listener()->semanticError(
          eq_constraint->ctx->start,
          absl::StrCat("Illegal constraint op for field '", field->name(),
                       "' in equality constraints."));
      return;
    }
    eq_constraint->value = value;
    // If the field_info doesn't exist, add a new field_info.
    auto name = field != nullptr ? field->name() : oneof->name();
    auto iter = field_map_.find(name);
    FieldInfo* field_info = nullptr;
    if (iter == field_map_.end()) {
      field_info = new FieldInfo{field, oneof};
      field_info->min_value = std::numeric_limits<int64_t>::max();
      field_info->max_value = std::numeric_limits<int64_t>::min();
      field_info->ctx = qualifed_ident_ctx;
      field_map_.emplace(name, field_info);
    } else {
      field_info = iter->second;
    }
    // Add a new entry for the value.
    field_info->unique_values += !field_info->value_map.contains(value);
    field_info->min_value = std::min(field_info->min_value, value);
    field_info->max_value = std::max(field_info->max_value, value);
    field_info->value_map.insert({value, enc});
  }
  encoding_vec_.push_back(enc);
  // Populate the other_* sets. These are used later to ensure that sub groups
  // aren't added with differentiators that are also used in other constraints.
  for (auto* constraint : enc->other_constraints()) {
    auto const* field = constraint->field_descriptor;
    auto const* oneof = field->containing_oneof();
    if (oneof != nullptr) {
      other_oneof_set_.insert(oneof);
      continue;
    }
    other_field_set_.insert(field);
  }
}

void ProtoEncodingGroup::AddSubGroups() {
  // If there is only one encoding, return.
  if (encoding_vec_.size() == 1) return;
  // First determine which field is the most productive to use to split up the
  // group. This is determined by how many values it has, with some thought to
  // the number of total values in its interval.
  // To start with just pick the one with the largest number of unique values,
  // as that should create a shallower decoding tree.
  FieldInfo* best_field = nullptr;
  absl::flat_hash_set<ProtoInstructionEncoding*> encodings;
  for (auto enc : encoding_vec_) {
    encodings.insert(enc);
  }
  for (auto& [unused, field_info] : field_map_) {
    // First check if the field is used in any other constraints, e.g., '>' or
    // '!='. If so, it is not a candidate for a direct lookup of the value.
    if (other_field_set_.contains(field_info->field)) continue;
    if (other_oneof_set_.contains(field_info->oneof)) continue;
    if (best_field == nullptr) {
      best_field = field_info;
    } else {
      if (field_info->unique_values > best_field->unique_values) {
        best_field = field_info;
      }
    }
  }
  // If there is no best field, or it doesn't differentiate we're done, but
  // first check the encodings to make sure there are no ambiguities or
  // duplicate encodings.
  if ((best_field == nullptr) || (best_field->unique_values == 1)) {
    CheckEncodings();
    return;
  }

  // Save the differentiating field info in this group.
  differentiator_ = best_field;

  // Next, create an encoding group for each value of the field, adding the
  // encodings that match the value to the corresponding groups.
  for (auto iter = best_field->value_map.begin();
       iter != best_field->value_map.end();
       /*empty*/) {
    auto* enc_group =
        new ProtoEncodingGroup(this, inst_group_, level_ + 1, error_listener_);
    int64_t value = iter->first;
    enc_group->set_value(value);
    while ((iter != best_field->value_map.end()) && (value == iter->first)) {
      // First create a copy of the encoding and remove the constraint
      // that corresponds with the field info, so it will not be considered
      // below.
      ProtoInstructionEncoding* enc =
          new ProtoInstructionEncoding(*(iter->second));
      // Remove the best_field constraint from the new encoding object.
      auto v_iter = enc->equal_constraints().begin();
      ProtoConstraint* constraint = nullptr;
      while (v_iter != enc->equal_constraints().end()) {
        constraint = *v_iter;
        if (constraint->op == ConstraintType::kEq) {
          if ((best_field->field != nullptr) &&
              (best_field->field == constraint->field_descriptor)) {
            break;
          }
        } else {  // This constraint is a kHas.
          if ((best_field->oneof != nullptr) &&
              (best_field->oneof ==
               constraint->field_descriptor->containing_oneof())) {
            break;
          }
        }
        ++v_iter;
      }
      if (v_iter != enc->equal_constraints().end()) {
        delete constraint->expr;
        delete constraint;
        enc->equal_constraints().erase(v_iter);
      }
      enc_group->AddEncoding(enc);
      // Remove the encoding from the map.
      encodings.erase(iter->second);
      ++iter;
    }
    encoding_group_vec_.push_back(enc_group);
  }
  // Any encodings remaining in the map have to be added to each of the sub
  // groups, as they weren't selected by value.
  for (auto enc : encodings) {
    for (auto* enc_group : encoding_group_vec_) {
      auto enc_copy = new ProtoInstructionEncoding(*enc);
      enc_group->AddEncoding(enc_copy);
    }
  }
  encodings.clear();
  // Recursively try to split the child encoding groups.
  for (auto* enc_group : encoding_group_vec_) {
    enc_group->AddSubGroups();
  }
}

// Check the encodings to make sure there aren't ambiguities.
void ProtoEncodingGroup::CheckEncodings() {
  // If there is only one encoding, there is no ambiguity.
  if (encoding_vec_.size() <= 1) return;
  // Encodings have to have additional constraints to differentiate between each
  // other, so check to see if any of them have none, and if so, signal an
  // error.
  for (auto* enc : encoding_vec_) {
    if (enc->equal_constraints().empty() && enc->other_constraints().empty()) {
      std::string msg =
          absl::StrCat("Decoding ambiguity between '", enc->name(), "' and :");
      for (auto* other_enc : encoding_vec_) {
        if (enc == other_enc) continue;
        absl::StrAppend(&msg, " '", other_enc->name(), "'");
      }
      error_listener()->semanticError(nullptr, msg);
      return;
    }
  }

  // Check for identical or overlapping constraints.

  // First sort the constraints in each vector.
  std::vector<std::vector<ProtoConstraint*>> constraints;
  constraints.reserve(encoding_vec_.size());
  for (auto* enc : encoding_vec_) {
    constraints.push_back({});
    for (auto* constraint : enc->equal_constraints()) {
      constraints.back().push_back(constraint);
    }
    for (auto* constraint : enc->other_constraints()) {
      constraints.back().push_back(constraint);
    }
  }
  for (int i = 0; i < constraints.size(); ++i) {
    std::sort(
        constraints[i].begin(), constraints[i].end(),
        [](const ProtoConstraint* lhs, const ProtoConstraint* rhs) -> bool {
          return lhs->field_descriptor->full_name() <
                 rhs->field_descriptor->full_name();
        });
  }
  // Now create value value sets for each field descriptor, combining multiple
  // constraints on the same field descriptor into a single set of values.
  std::vector<std::vector<ProtoConstraintValueSet*>> value_sets;
  value_sets.reserve(encoding_vec_.size());
  for (auto const& constraint_vec : constraints) {
    const google::protobuf::FieldDescriptor* previous = nullptr;
    value_sets.push_back({});
    for (auto const* constraint : constraint_vec) {
      // If it's the first occurance of a field descriptor, create a new
      // range on this constraint.
      ProtoConstraintValueSet* value_set = nullptr;
      if (previous != constraint->field_descriptor) {
        previous = constraint->field_descriptor;
        value_set = new ProtoConstraintValueSet(constraint);
        value_sets.back().push_back(value_set);
        continue;
      }
      // This is not the first occurance of a field descriptor. Intersect
      // with the current range.
      auto status =
          value_set->IntersectWith(ProtoConstraintValueSet(constraint));
      // Check for error.
      if (!status.ok()) {
        // Clean up.
        for (auto& value_set_list : value_sets) {
          for (auto* value_set : value_set_list) delete value_set;
        }
        value_sets.clear();
        // Signal error.
        error_listener()->semanticError(nullptr, status.message());
        return;
      }
    }
  }
  for (int i = 0; i < value_sets.size(); ++i) {
    for (int j = i + 1; j < value_sets.size(); ++j) {
      if (DoConstraintsOverlap(value_sets[i], value_sets[j])) {
        error_listener()->semanticError(
            nullptr, absl::StrCat("Encoding group '", inst_group_->name(),
                                  "': encoding ambiguity between '",
                                  encoding_vec_[i]->name(), " and ",
                                  encoding_vec_[j]->name(), "'"));
      }
    }
  }
  // Clean up.
  for (auto& value_set_list : value_sets) {
    for (auto* value_set : value_set_list) delete value_set;
  }
}

// Determine if the constraints overlap for two encodings lhs and rhs based on
// the value sets.
bool ProtoEncodingGroup::DoConstraintsOverlap(
    const std::vector<ProtoConstraintValueSet*>& lhs,
    const std::vector<ProtoConstraintValueSet*>& rhs) {
  auto iter_lhs = lhs.begin();
  auto iter_rhs = rhs.begin();
  while ((iter_lhs != lhs.end()) && (iter_rhs != rhs.end())) {
    // The constraint value sets are sorted by field descriptor name, so if
    // the field descriptors are different, then the constraints do not overlap.
    if ((*iter_lhs)->field_descriptor()->full_name() !=
        (*iter_rhs)->field_descriptor()->full_name()) {
      return false;
    }
    ProtoConstraintValueSet lhs_copy(**(iter_lhs));
    auto status = lhs_copy.IntersectWith(**(iter_rhs));
    // If there is an error taking the intersection, return true to signify
    // an overlap, even if there isn't one.
    if (!status.ok()) return true;
    // If the intersection is empty, then they don't overlap. No need to check
    // further.
    if (lhs_copy.IsEmpty()) return false;
    ++iter_lhs;
    ++iter_rhs;
  }
  // If there are additional constraint value sets for either instruction, then
  // they don't overlap.
  if ((iter_lhs != lhs.end()) || (iter_rhs != rhs.end())) {
    return false;
  }
  return true;
}

constexpr char kDecodeMsgName[] = "inst_proto";

std::string ProtoEncodingGroup::EmitLeafDecoder(
    absl::string_view fcn_name, absl::string_view opcode_enum,
    absl::string_view message_type_name, int indent_width) const {
  std::string output;
  std::string if_sep;
  std::string decoder_class =
      ToPascalCase(inst_group_->encoding_info()->decoder()->name()) + "Decoder";
  absl::StrAppend(&output, std::string(indent_width, ' '), opcode_enum, " ",
                  fcn_name, "(", message_type_name, " ", kDecodeMsgName, ", ",
                  decoder_class, " *decoder) {\n");
  indent_width += 2;
  std::string indent(indent_width, ' ');
  // Check for the case when there is only a single encoding with no
  // constraints.
  if ((encoding_vec_.size() == 1) &&
      encoding_vec_[0]->equal_constraints().empty() &&
      encoding_vec_[0]->other_constraints().empty()) {
    absl::StrAppend(
        &output, encoding_vec_[0]->GetSetterCode(kDecodeMsgName, indent_width),
        "return ", opcode_enum, "::k", ToPascalCase(encoding_vec_[0]->name()),
        ";\n");
    indent_width -= 2;
    absl::StrAppend(&output, std::string(indent_width, ' '), "}\n\n");
    return output;
  }

  // Helper lambda.
  auto generate_condition =
      [](const ProtoConstraint* constraint) -> std::string {
    std::string output;
    if (constraint->op == ConstraintType::kHas) {
      std::string ident = constraint->ctx->qualified_ident()->getText();
      auto pos = ident.find_last_of('.');
      std::string prefix;
      if (pos != std::string::npos) {
        prefix = absl::StrCat(".", ident.substr(0, pos + 1));
      }
      auto oneof_desc = constraint->field_descriptor->containing_oneof();
      auto oneof_name = oneof_desc->name();
      std::string parent_name;
      for (auto parent = oneof_desc->containing_type(); parent != nullptr;
           parent = parent->containing_type()) {
        absl::StrAppend(&parent_name, ToPascalCase(parent->name()), "::");
      }
      auto package = absl::StrReplaceAll(
          constraint->field_descriptor->file()->package(), {{".", "::"}});
      return absl::StrCat(
          "(", kDecodeMsgName, prefix, ".", oneof_name, "_case() == ", package,
          "::", parent_name, ToPascalCase(oneof_name), "Case::k",
          ToPascalCase(constraint->field_descriptor->name()), ")");
    } else {
      return absl::StrCat("(", kDecodeMsgName, ".",
                          constraint->ctx->field->getText(), " ",
                          GetOpText(constraint->op), " ",
                          constraint->ctx->constraint_expr()->getText(), ")");
    }
  };

  // Generate a chained if-else if-else-statement for the encodings in the
  // encoding vector.
  std::string indent_body(indent_width + 2, ' ');
  for (auto* enc : encoding_vec_) {
    // Generate the if statement conditions.
    absl::StrAppend(&output, indent, if_sep, "if (");
    std::string cond_sep;
    for (auto const* constraint : enc->equal_constraints()) {
      absl::StrAppend(&output, cond_sep, generate_condition(constraint));
      cond_sep = " && ";
    }
    for (auto const* constraint : enc->other_constraints()) {
      absl::StrAppend(&output, cond_sep, generate_condition(constraint));
      cond_sep = " && ";
    }
    absl::StrAppend(&output, ") {\n");

    // Generate if statement body.
    absl::StrAppend(&output, indent_body,
                    enc->GetSetterCode(kDecodeMsgName, indent_width + 2),
                    "return ", opcode_enum, "::k", ToPascalCase(enc->name()),
                    ";\n");

    if_sep = "} else ";
  }
  // Generate the fall through.
  absl::StrAppend(&output, indent, "}\n", indent, "return ", opcode_enum,
                  "::kNone;\n");
  indent_width -= 2;
  absl::StrAppend(&output, std::string(indent_width, ' '), "}\n\n");
  return output;
}

namespace {

bool LessThan(ProtoEncodingGroup* lhs, ProtoEncodingGroup* rhs) {
  return lhs->value() < rhs->value();
}

}  // namespace

std::string ProtoEncodingGroup::EmitComplexDecoder(
    absl::string_view fcn_name, absl::string_view opcode_enum,
    absl::string_view message_type_name) {
  std::string output;
  if (encoding_group_vec_.empty()) {
    return EmitLeafDecoder(fcn_name, opcode_enum, message_type_name, 0);
  }
  std::string decoder_class =
      ToPascalCase(inst_group_->encoding_info()->decoder()->name()) + "Decoder";
  // First emit the function call tables.
  // Sort the encoding_group_vec according to differentiator value.
  std::sort(encoding_group_vec_.begin(), encoding_group_vec_.end(), LessThan);
  // Now emit the decoder function.
  double density =
      (double)differentiator_->unique_values /
      (double)(differentiator_->max_value - differentiator_->min_value);
  if (density < 0.75) {
    std::string map_name = absl::StrCat(ToSnakeCase(fcn_name), "_map");
    absl::StrAppend(
        &output,
        "absl::NoDestructor<absl::flat_hash_map<int32_t, std::function<",
        opcode_enum, "(", message_type_name, ", ", decoder_class, "*)>>> ",
        map_name, "({\n");
    for (auto* enc_group : encoding_group_vec_) {
      auto enc_value = enc_group->value();
      absl::StrAppend(&output, "  {", enc_value, ", ", fcn_name, "_", enc_value,
                      "},\n");
    }
    absl::StrAppend(&output, "});\n\n");
    // Emit the function body.
    auto call =
        absl::StrReplaceAll(differentiator_->ctx->getText(), {{".", "()."}});
    absl::StrAppend(&output, opcode_enum, " ", fcn_name, "(", message_type_name,
                    " ", kDecodeMsgName, ", ", decoder_class, " *decoder) {\n",
                    "  auto iter = ", map_name, "->find(", kDecodeMsgName, ".",
                    call, "());\n", "  if (iter == ", map_name,
                    "->end()) return ", opcode_enum, "::kNone;\n",
                    "  return iter->second(", kDecodeMsgName,
                    ", decoder);\n}\n\n");
  } else {
    auto min = differentiator_->min_value;
    auto max = differentiator_->max_value;
    auto num_values = max - min + 1;
    auto iter = encoding_group_vec_.begin();
    absl::StrAppend(&output, "std::function<", opcode_enum, "(",
                    message_type_name, ", ", decoder_class, "*)> ",
                    ToSnakeCase(fcn_name), "_table[", num_values, "] = {\n");
    // Fill in the entries in the function table.
    for (int i = 0; i < num_values; ++i) {
      auto enc_value = iter != encoding_group_vec_.end()
                           ? (*iter)->value()
                           : std::numeric_limits<int64_t>::min();
      auto index = enc_value - min;
      if (index != i) {
        absl::StrAppend(&output, "  Decode", ToPascalCase(inst_group_->name()),
                        "_None,\n");
      } else {
        absl::StrAppend(&output, "  ", fcn_name, "_", enc_value, ",\n");
        ++iter;
      }
    }
    // Emit the function body.
    auto call =
        absl::StrReplaceAll(differentiator_->ctx->getText(), {{".", "()."}});
    absl::StrAppend(
        &output, "};\n\n", opcode_enum, " ", fcn_name, "(", message_type_name,
        " ", kDecodeMsgName, ", ", decoder_class, " *decoder) {\n", "  return ",
        ToSnakeCase(fcn_name), "_table[", kDecodeMsgName, ".", call, "() - ",
        differentiator_->min_value, "](", kDecodeMsgName, ", decoder);\n}\n\n");
  }
  return output;
}

std::string ProtoEncodingGroup::EmitDecoders(
    absl::string_view fcn_name, absl::string_view opcode_enum,
    absl::string_view message_type_name) {
  std::string output;
  // Emit decoders for subordinate groups (lower in the hierarchy).
  for (auto* enc_group : encoding_group_vec_) {
    absl::StrAppend(
        &output,
        enc_group->EmitDecoders(absl::StrCat(fcn_name, "_", enc_group->value()),
                                opcode_enum, message_type_name));
  }
  // Emit decoder for this group.
  absl::StrAppend(&output,
                  EmitComplexDecoder(fcn_name, opcode_enum, message_type_name));
  return output;
}

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