// 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.

#ifndef MPACT_SIM_DECODER_PROTO_INSTRUCTION_ENCODING_H_
#define MPACT_SIM_DECODER_PROTO_INSTRUCTION_ENCODING_H_

#include <cstdint>
#include <string>
#include <vector>

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

namespace proto2 {
class FieldDescriptor;
}

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

enum class ConstraintType : int { kEq = 0, kNe, kLt, kLe, kGt, kGe, kHas };

inline std::string GetOpText(ConstraintType op) {
  switch (op) {
    case ConstraintType::kEq:
      return "==";
    case ConstraintType::kNe:
      return "!=";
    case ConstraintType::kLt:
      return "<";
    case ConstraintType::kLe:
      return "<=";
    case ConstraintType::kGt:
      return ">";
    case ConstraintType::kGe:
      return ">=";
    case ConstraintType::kHas:
      return "";
  }
}

// Struct to store information about an encoding constraint for an instruction.
struct ProtoConstraint {
  // Parsing context.
  FieldConstraintCtx* ctx;
  // The proto field descriptor for which the constraint applies.
  const google::protobuf::FieldDescriptor* field_descriptor;
  // The constraint type.
  ConstraintType op;
  // If non-null, the expression that applies to the constraint.
  const ProtoConstraintExpression* expr;
  // If the value is compatible with int64_t, the value of the expression. This
  // is filled in later when the expression is evaluated for decoding purposes.
  int64_t value;
  // If non-null, points to a constraint that has to be true before one can
  // evaluate this constraint.
  ProtoConstraint* depends_on;
  // Constructors.
  ProtoConstraint(FieldConstraintCtx* ctx,
                  const google::protobuf::FieldDescriptor* field_descriptor,
                  ConstraintType op, const ProtoConstraintExpression* expr,
                  int64_t value, ProtoConstraint* depends_on)
      : ctx(ctx),
        field_descriptor(field_descriptor),
        op(op),
        expr(expr),
        value(value),
        depends_on(depends_on) {}
  ProtoConstraint(FieldConstraintCtx* ctx,
                  const google::protobuf::FieldDescriptor* field_descriptor,
                  ConstraintType op)
      : ProtoConstraint(ctx, field_descriptor, op, nullptr, 0, nullptr) {}
  // Copy constructor.
  ProtoConstraint(const ProtoConstraint& rhs) {
    this->ctx = rhs.ctx;
    this->field_descriptor = rhs.field_descriptor;
    this->op = rhs.op;
    this->expr = rhs.expr != nullptr ? rhs.expr->Clone() : nullptr;
    this->value = rhs.value;
    this->depends_on = rhs.depends_on;
  }
};

// Struct to store information about a setter for an instruction encoding.
struct ProtoSetter {
  // Proto setter context.
  SetterDefCtx* ctx;
  // The name of the object that is set.
  std::string name;
  // The field that will provide the type and value of the object.
  const google::protobuf::FieldDescriptor* field_descriptor;
  // Default value of the object if the field descriptor is not valid.
  IfNotCtx* if_not;
  // If non-null, points to constraint that has to be true in order to access
  // the value of the field described by field_descriptor.
  ProtoConstraint* depends_on;
};

class ProtoInstructionGroup;

// This class captures all the encoding constraints and the setters for one
// instruction in an instruction group.
class ProtoInstructionEncoding {
 public:
  ProtoInstructionEncoding(std::string name, ProtoInstructionGroup* parent);
  ProtoInstructionEncoding(const ProtoInstructionEncoding& rhs);
  ProtoInstructionEncoding() = delete;
  ProtoInstructionEncoding& operator=(
      const ProtoInstructionEncoding& encoding) = delete;
  ~ProtoInstructionEncoding();

  // Adds a value setter that is executed when the instruction is successfully
  // decoded. This is used to make values, such as register numbers, immediate
  // values, etc., that could be stored in a nested one_of submessage, available
  // at known names.
  absl::Status 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);
  // Adds an encoding constraint for the current instruction. Encoding
  // constraints provide constraints on values of proto message fields that
  // have to be satisfied in order for the instruction to match.
  absl::Status AddConstraint(
      FieldConstraintCtx* ctx, ConstraintType op,
      const google::protobuf::FieldDescriptor* field_descriptor,
      const std::vector<const google::protobuf::FieldDescriptor*>&
          one_of_fields,
      const ProtoConstraintExpression* expr);

  // Call when the setters and constraints have been added in order to generate
  // the setter code into the setter_code_ variable.
  void GenerateSetterCode();
  // Get setter code, substituting 'message_name' for '$' in the text.
  std::string GetSetterCode(absl::string_view message_name, int indent) const;
  // Getters.
  const std::string& name() const { return name_; }
  ProtoInstructionGroup* instruction_group() const {
    return instruction_group_;
  }
  std::vector<ProtoConstraint*>& equal_constraints() {
    return equal_constraints_;
  }
  std::vector<ProtoConstraint*>& other_constraints() {
    return other_constraints_;
  }
  absl::flat_hash_map<std::string, ProtoConstraint*>& has_constraints() {
    return has_constraints_;
  }

  std::string setter_code() const { return setter_code_; }

 private:
  // Returns a pointer to the constraint for field_descriptor if it exists. If
  // it does not exist, it creates it and adds it to the has_constraints and
  // returns a pointer to the new constraint. If depends_on is not nullptr,
  // then it is required that the depends_on constraint exists in the
  // has_constraints_ map. This is checked by searching for the full_name of
  // the field_descriptor in the depends_on constraint.
  ProtoConstraint* AddHasConstraint(
      const google::protobuf::FieldDescriptor* field_descriptor,
      ProtoConstraint* depends_on);

  // Instruction name.
  std::string name_;
  // Parent instruction group.
  ProtoInstructionGroup* instruction_group_ = nullptr;
  // Setter code for this encoding.
  std::string setter_code_;
  // Map from setter names to the setter structs.
  absl::btree_map<std::string, ProtoSetter*> setter_map_;
  // Map from one_of descriptor to field.
  absl::flat_hash_map<const google::protobuf::OneofDescriptor*,
                      const google::protobuf::FieldDescriptor*>
      oneof_field_map_;
  // "equal-to" field constraints.
  std::vector<ProtoConstraint*> equal_constraints_;
  // All other constraints.
  std::vector<ProtoConstraint*> other_constraints_;
  // Has Constraints, these are required one_of members that other constraints
  // may depend on.
  absl::flat_hash_map<std::string, ProtoConstraint*> has_constraints_;
};

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

#endif  // MPACT_SIM_DECODER_PROTO_INSTRUCTION_ENCODING_H_
