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

#include <string>
#include <utility>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/decoder/bin_decoder.h"
#include "mpact/sim/decoder/decoder_error_listener.h"
#include "mpact/sim/decoder/format.h"
#include "mpact/sim/decoder/instruction_group.h"

namespace mpact {
namespace sim {
namespace decoder {
namespace bin_format {

BinEncodingInfo::BinEncodingInfo(std::string opcode_enum,
                                 DecoderErrorListener *error_listener)
    : opcode_enum_(opcode_enum), error_listener_(error_listener) {}

BinEncodingInfo::~BinEncodingInfo() {
  delete decoder_;
  for (auto &[unused, format_ptr] : format_map_) {
    delete format_ptr;
  }
  format_map_.clear();
  for (auto &[unused, group_ptr] : instruction_group_map_) {
    delete group_ptr;
  }
  instruction_group_map_.clear();
}

// Add name of an include file to be included in the generated code.
void BinEncodingInfo::AddIncludeFile(std::string include_file) {
  include_files_.insert(std::move(include_file));
}

// Adding a format that does not have a parent (to inherit from ).
absl::StatusOr<Format *> BinEncodingInfo::AddFormat(std::string name,
                                                    int width) {
  // Verify that the format name hasn't been used.
  if (format_map_.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Error: format '", name, "' already defined"));
  }
  auto format = new Format(name, width, this);
  format_map_.emplace(name, format);
  return format;
}

// Adding a format that does have a parent.
absl::StatusOr<Format *> BinEncodingInfo::AddFormat(std::string name, int width,
                                                    std::string parent_name) {
  // Verify that the format name hasn't been used.
  if (format_map_.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Error: format '", name, "' already defined"));
  }
  auto format = new Format(name, width, parent_name, this);
  format_map_.emplace(name, format);
  return format;
}

// Lookup a format by name. Return nullptr if it isn't found.
Format *BinEncodingInfo::GetFormat(absl::string_view name) const {
  auto iter = format_map_.find(name);
  if (iter == format_map_.end()) return nullptr;
  return iter->second;
}

// Add the named instruction group. Instruction encodings are added directly
// to the group using the returned pointer.
absl::StatusOr<InstructionGroup *> BinEncodingInfo::AddInstructionGroup(
    std::string name, int width, std::string format_name) {
  if (instruction_group_map_.contains(name)) {
    return absl::AlreadyExistsError(
        absl::StrCat("Error: instruction group '", name, "' already defined"));
  }
  auto group =
      new InstructionGroup(name, width, format_name, opcode_enum_, this);
  instruction_group_map_.emplace(name, group);
  return group;
}

// Top level method that calls the checking method of each format. This is
// called after all the formats have been added.
void BinEncodingInfo::PropagateExtractors() {
  for (auto &[unused, format] : format_map_) {
    // For the base formats (those who do not inherit from another format).
    if (format->base_format() == nullptr) {
      format->PropagateExtractorsUp();
    }
  }

  for (auto &[unused, format] : format_map_) {
    if (format->base_format() == nullptr) {
      format->PropagateExtractorsDown();
    }
  }
}

BinDecoder *BinEncodingInfo::AddBinDecoder(std::string name) {
  if (decoder_ != nullptr) {
    error_listener_->semanticError(nullptr, "Can only select one decoder");
    return nullptr;
  }
  auto *bin_decoder = new BinDecoder(name, this, error_listener());
  decoder_ = bin_decoder;
  return bin_decoder;
}

}  // namespace bin_format
}  // namespace decoder
}  // namespace sim
}  // namespace mpact
