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

#include <string>
#include <utility>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.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_encoding_group.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 "src/google/protobuf/descriptor.h"

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

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

ProtoInstructionGroup::ProtoInstructionGroup(
    std::string group_name, const google::protobuf::Descriptor* message_type,
    std::string opcode_enum, ProtoEncodingInfo* encoding_info)
    : name_(group_name),
      message_type_(message_type),
      opcode_enum_(opcode_enum),
      encoding_info_(encoding_info) {}

ProtoInstructionGroup::~ProtoInstructionGroup() {
  for (auto* encoding : encodings_) {
    delete encoding;
  }
  encodings_.clear();
  delete encoding_group_;
  encoding_group_ = nullptr;
  for (auto& [unused, setter_map] : setter_groups_) {
    for (auto& [unused, setter_info] : setter_map) {
      delete setter_info;
    }
    setter_map.clear();
  }
  setter_groups_.clear();
}

ProtoInstructionEncoding* ProtoInstructionGroup::AddInstructionEncoding(
    std::string name) {
  auto* encoding = new ProtoInstructionEncoding(name, this);
  encodings_.push_back(encoding);
  return encoding;
}

absl::StatusOr<
    std::pair<absl::btree_map<std::string, SetterInfo*>::const_iterator,
              absl::btree_map<std::string, SetterInfo*>::const_iterator>>
ProtoInstructionGroup::GetSetterGroup(absl::string_view group) const {
  auto map_iter = setter_groups_.find(group);
  if (map_iter == setter_groups_.end()) {
    return absl::NotFoundError(absl::StrCat("No setter group '", group, "'."));
  }
  return std::pair<absl::btree_map<std::string, SetterInfo*>::const_iterator,
                   absl::btree_map<std::string, SetterInfo*>::const_iterator>{
      map_iter->second.begin(), map_iter->second.end()};
}

// Add a group level setter.
absl::Status ProtoInstructionGroup::AddSetter(
    const std::string& group_name, SetterDefCtx* ctx,
    const std::string& setter_name,
    const google::protobuf::FieldDescriptor* field_desc,
    std::vector<const google::protobuf::FieldDescriptor*> one_of_fields,
    IfNotCtx* if_not) {
  auto map_iter = setter_groups_.find(group_name);
  if (map_iter == setter_groups_.end()) {
    auto [iter, unused] = setter_groups_.insert({group_name, {}});
    map_iter = iter;
  }
  if (map_iter->second.contains(setter_name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Duplicate setter name '", setter_name,
                     "' in setter group '", group_name, "'."));
  }
  auto* setter_info =
      new SetterInfo({ctx, setter_name, field_desc, one_of_fields, if_not});
  map_iter->second.insert({setter_name, setter_info});
  return absl::OkStatus();
}

void ProtoInstructionGroup::CopyInstructionEncoding(
    ProtoInstructionEncoding* encoding) {
  if (encoding_name_set_.contains(encoding->name())) {
    encoding_info_->error_listener()->semanticWarning(
        nullptr, absl::StrCat("Duplicate instruction opcode name '",
                              encoding->name(), "' in group '", name(), "'."));
  }
  encoding_name_set_.insert(encoding->name());
  encodings_.push_back(encoding);
}

void ProtoInstructionGroup::ProcessEncodings(
    DecoderErrorListener* error_listener) {
  // Create a new encoding group for this instruction group and add all the
  // encodings to it.
  encoding_group_ = new ProtoEncodingGroup(this, 0, error_listener);
  for (auto* encoding : encodings_) {
    encoding_group_->AddEncoding(new ProtoInstructionEncoding(*encoding));
  }
  // Call the encoding group to break it into a proper decoding hierarchy.
  encoding_group_->AddSubGroups();
}

std::string ProtoInstructionGroup::GenerateDecoder() const {
  if (encoding_group_ == nullptr) {
    return absl::StrCat("#error No decoder generated for instruction group '",
                        name(), "'.");
  }
  std::string output;
  if (message_type_ == nullptr) {
    absl::StrAppend(&output, "\n#error No message type for instruction group '",
                    name(), "'.\n");
    return output;
  }
  std::string qualified_message_type =
      absl::StrReplaceAll(message_type_->full_name(), {{".", "::"}});
  std::string message_type = ToPascalCase(name()) + "MessageType";
  absl::StrAppend(
      &output, "\n// Decoding functions for instruction group: ", name(), "\n");
  absl::StrAppend(&output, "namespace {\n\n");
  absl::StrAppend(&output, encoding_info_->opcode_enum(), " ", "Decode",
                  ToPascalCase(name()), "_None(", message_type, ", ",
                  ToPascalCase(encoding_info_->decoder()->name()),
                  "Decoder *) {\n", "  return ", encoding_info_->opcode_enum(),
                  "::kNone;\n}\n\n");
  absl::StrAppend(&output, encoding_group_->EmitDecoders(
                               "Decode" + ToPascalCase(name()),
                               encoding_info_->opcode_enum(), message_type));
  absl::StrAppend(&output, "}  // namespace\n\n");
  return output;
}

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