/*******************************************************************************
 *
 * File:     Unit.h
 *
 * Contents: Declaration of Unit base-class.
 *
 * Copyright 2017
 *
 * Author: David Juhasz (david.juhasz@tuwien.ac.at)
 *
 ******************************************************************************/

#ifndef ROSA_CORE_UNIT_H
#define ROSA_CORE_UNIT_H

#include "rosa/support/atom.hpp"

#include "rosa/core/forward_declarations.h"

#include <ostream>
#include <string>

namespace rosa {

// Base class for every entity in the system that has to be identified and
// traced.
// NOTE: Life-cycle of Unit instances is supposed to be managed by a System, do
// not create and destroy a Unit directly.
class Unit {
public:

  // Identifies the kind of the Unit.
  // NOTE: Kind is dependent on the owning System.
  const AtomValue Kind;

  // System-assigned unique identifier of the Unit instance,
  // based on the static member field CountUnits.
  const id_t Id;

  // Textual identifier of the Unit instance. Defaults to a text referring to
  // the Id value of the Unit, unless otherwise defined via a constructor
  // argument. The Name of a Unit is not necessarily unique in the system.
  const std::string Name;

protected:
  // The owning System.
  System &S;

public:
  // Full qualified name of the Unit instance.
  const std::string FullName;

public:
  // Ctor.
  // PRE: !Name.empty()
  Unit(const AtomValue Kind, const id_t Id, const std::string &Name,
       System &S) noexcept;

  // No copy and move.
  Unit(const Unit &) = delete;
  Unit(Unit &&) = delete;
  Unit &operator=(const Unit &) = delete;
  Unit &operator=(Unit &&) = delete;

  // Dtor.
  virtual ~Unit(void);

  // Dumping the object into a string for tracing purposes,
  // subclasses are supposed to override this function.
  virtual std::string dump(void) const noexcept;

protected:
  // Returns a reference to the owning System.
  // NOTE: Subclasses may override the function to return a reference of a
  // special System subtype.
  virtual System &system() const noexcept;
};

// Helper function dumping the given Unit instance to the given output stream.
std::ostream &operator<<(std::ostream &OS, const Unit &U);

} // End namespace rosa

#endif // ROSA_CORE_UNIT_H

