// 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/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();
}

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