// 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 LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_
#define LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_

#include <memory>
#include <string>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"

// This file provides classes to facilitate modeling program errors/exceptions
// and store appropriate error messages in a "controller". The controller allows
// program errors to be masked or unmasked by name. There is also an internal
// simulation program error name where any detected simulator errors (as opposed
// to simulated architecture errors) can be raised.
//
// The idea is that code that is responsible for instruction issue and control
// uses this code to detect when a program error/exception has been raised and
// based on the type/masking status of the error acts accordingly.
//
// Different simulator constructs use ProgramError instances to signal error
// occurrences to the ProgramErrorController.
//
// Note: The term exception is used to describe the hardware exception or
// program error that may be raised on a simulated target architecture. It does
// not refer to C++ exceptions.

namespace mpact {
namespace sim {
namespace generic {

class ProgramError;

// The ProgramErrorController keeps track of errors that have been raised
// during the simulation, or by the simulator itself (for internal errors).
// It supports masked and unmasked errors. It does not by itself perform any
// actions in response to a reported error.
class ProgramErrorController {
 public:
  // Name for internal simulator errors.
  static constexpr char kInternalErrorName[] = "internal_simulator_error";

  explicit ProgramErrorController(absl::string_view name);

  // Clears the named program error (masked or unmasked).
  void Clear(absl::string_view program_error_name);

  // Clears all errors (masked or unmasked).
  void ClearAll();

  // Masks the named program error.
  void Mask(absl::string_view program_error_name);

  // Unmasks the named program error.
  void Unmask(absl::string_view program_error_name);

  // Returns true if the named program error is masked.
  bool IsMasked(absl::string_view program_error_name);

  // Returns true if any program errors have been set.
  bool HasError() const;

  // Returns true if a masked program error has been set.
  bool HasMaskedError() const;

  // Returns true if an unmasked program error has been set.
  bool HasUnmaskedError() const;

  // Returns a vector of active masked program error names. Active in this
  // context means that they have not been cleared since they were raised.
  std::vector<std::string> GetMaskedErrorNames() const;

  // Returns a vector of active, unmasked program error names.
  std::vector<std::string> GetUnmaskedErrorNames() const;

  // Returns a reference to the vector of error messages associated with the
  // named program error. If there is no such program_error_name the internal
  // error is raised (see kInternalErrorName), and the error messages for that
  // are returned.
  const std::vector<std::string> &GetErrorMessages(
      absl::string_view program_error_name);

  // Raises the named program error and adds the error message to its message
  // queue. This method is intended to be called from a ProgramError instance.
  void Raise(absl::string_view program_error_name,
             absl::string_view error_message);

  // Add a program error name to the controller, return true if it was added
  // successfully. Return false if it already exists.
  bool AddProgramErrorName(absl::string_view program_error_name);
  // Returns true if the program error name has already been added to the
  // controller.
  bool HasProgramErrorName(absl::string_view program_error_name);
  // Return a unique_ptr to a ProgramError instance tied to a program error that
  // already exists in the controller. Returns a nullptr if the program error
  // doesn't exist.
  std::unique_ptr<ProgramError> GetProgramError(
      absl::string_view program_error_name);

  // Accessors.
  absl::string_view name() const { return name_; }

 private:
  // Internal method used to insert a program error into the map and vector.
  void Insert(absl::string_view name);

  std::string name_;
  struct ProgramErrorInfo {
    std::string name;
    bool is_masked;
    std::vector<std::string> error_messages;
    explicit ProgramErrorInfo(absl::string_view error_name)
        : name(error_name), is_masked(false) {}
  };
  absl::flat_hash_map<std::string, int> program_error_map_;
  absl::flat_hash_set<int> unmasked_program_errors_;
  absl::flat_hash_set<int> masked_program_errors_;
  std::vector<ProgramErrorInfo> program_error_info_;
};

// The ProgramError class is used as a handle to report a particular program
// error or exception. Each ProgramError instance is tied to a particular
// error or exception type.
class ProgramError {
  friend class ProgramErrorController;

 private:
  // The constructor is private, as the handle is obtained from a
  // ProgramErrorController instance.
  ProgramError(absl::string_view name, ProgramErrorController *controller);

 public:
  // Raise the error to the ProgramErrorController with the given additional
  // error message.
  void Raise(absl::string_view error_message);
  // Accessor.
  absl::string_view name() const { return name_; }

 private:
  std::string name_;
  ProgramErrorController *controller_;
};

}  // namespace generic
}  // namespace sim
}  // namespace mpact

#endif  // LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_
