// 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_GENERIC_COMPONENT_H_
#define MPACT_SIM_GENERIC_COMPONENT_H_

#include <functional>
#include <string>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/generic/config.h"
#include "mpact/sim/generic/counters_base.h"
#include "mpact/sim/proto/component_data.pb.h"

namespace mpact {
namespace sim {
namespace generic {

// A Component represents an abstraction of a hierarchical block of the
// simulated architecture. It may, but is not required to correspond to a block
// in the actual hardware design. By itself it has no real functionality in the
// simulation, but acts as a named entity that can have configurations and/or
// counter instrumentation instances associated with it, as well as zero or more
// Component instances as children. In general, it is expected that there is
// only one root instance of a Component.
class Component {
 public:
  // Using btree_map to ensure proto exports are done in name order.
  using ComponentMap = absl::btree_map<std::string, Component *>;
  using CounterMap = absl::btree_map<std::string, CounterBaseInterface *>;
  using ConfigMap = absl::btree_map<std::string, ConfigBase *>;
  // Type alias for import done callback function.
  using CallbackFunction = std::function<void()>;
  // Create a Component with no parent.
  explicit Component(std::string name);
  // Create a Component under the given parent. Adds the component to the
  // parent's child components.
  Component(std::string name, Component *parent);
  Component() = delete;
  Component(const Component &) = delete;
  Component operator=(const Component &) = delete;
  virtual ~Component() = default;

  // Methods to add and access child components, counters and config entries.
  absl::Status AddChildComponent(Component &child);
  absl::Status AddCounter(CounterBaseInterface *counter);
  absl::Status AddConfig(ConfigBase *config);
  Component *GetChildComponent(absl::string_view name) const;
  absl::Status RemoveChildComponent(absl::string_view name);
  CounterBaseInterface *GetCounter(absl::string_view name) const;
  ConfigBase *GetConfig(absl::string_view name) const;

  // Imports the ComponentData proto into the current Component, registered
  // child component instances, and registered ConfigBase instances. No values
  // are imported into counters. This method may be overridden.
  virtual absl::Status Import(
      const mpact::sim::proto::ComponentData &component_data);

  // This method is called when all imports are done. Can be overridden.
  virtual void ImportDone() const;

  // Register a callback function to be called when import is done.
  template <typename F>
  void AddImportDoneCallback(const F &callback) {
    callback_vec_.push_back(callback);
  }

  // Exports the data from the current Component instance, its' registered child
  // components, registered ConfigBase instances, and registered CounterBase
  // instances.
  absl::Status Export(proto::ComponentData *component_data);

  // Accessors.
  const std::string &component_name() const { return component_name_; }
  Component *parent() const { return parent_; }

  // Map accessors.
  const ComponentMap &child_map() const { return child_map_; }
  const CounterMap &counter_map() const { return counter_map_; }
  const ConfigMap &config_map() const { return config_map_; }

 protected:
  // The Import method is divided into import self and import children. Each
  // can be individually overridden.
  virtual absl::Status ImportSelf(
      const mpact::sim::proto::ComponentData &component_data);
  virtual absl::Status ImportChildren(
      const mpact::sim::proto::ComponentData &component_data);

 private:
  // Private accessor.
  void SetParent(Component *parent) { parent_ = parent; }

  std::string component_name_;
  Component *parent_ = nullptr;

  // None of the objects pointed to by these maps are owned by this object.
  ComponentMap child_map_;
  CounterMap counter_map_;
  ConfigMap config_map_;
  std::vector<CallbackFunction> callback_vec_;
};

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

#endif  // MPACT_SIM_GENERIC_COMPONENT_H_
