#pragma once

#include <register/hei_hardware_register.hpp>
#include <util/hei_flyweight.hpp>

namespace libhei
{

/**
 * @brief A Power Systems SCOM register.
 *
 * Address width:   4 bytes
 * Register width:  8 bytes
 * Bit order:       Ascending (0-63 left to right)
 */
class ScomRegister : public HardwareRegister
{
  public: // Constructor, destructors, assignment, etc.

    /**
     * @brief Constructor from components.
     * @param i_chipType    Type of chip associated with this register.
     * @param i_id          Unique ID for this register.
     * @param i_instance    Instance of this register
     * @param i_accessLevel Hardware access level for this register.
     * @param i_address     A 4-byte address for this SCOM register.
     */
    ScomRegister( ChipType_t i_chipType, RegisterId_t i_id,
                  RegisterInstance_t i_instance,
                  RegisterAccessLevel_t i_accessLevel, uint32_t i_address ) :
        HardwareRegister( i_chipType, i_id, i_instance, i_accessLevel ),
        iv_address( i_address )
    {}

    /** @brief Destructor. */
    ~ScomRegister() = default;

  private:

    // This is needed to allow the flyweights to use the copy constructor, but
    // not allow it to be used in general.
    friend class Flyweight<ScomRegister>;

    /**
     * @brief Copy constructor.
     *
     * Needed by Flyweight class, but should not be allowed in general.
     */
    ScomRegister( const ScomRegister & ) = default;

    /**
     * @brief Explicitly disables assignment operator.
     *
     * This is redundant since the compilier will implicitly delete this because
     * of the constant instance variables, but helps communicate it is not
     * allowed.
     */
    ScomRegister & operator=( const ScomRegister & ) = delete;

  public: // Accessor functions

    /** Function overloaded from parent HardwareRegister class. */
    RegisterType_t getRegisterType() const { return REG_TYPE_SCOM; }

    /** Function overloaded from parent HardwareRegister class. */
    RegisterAddress_t getAddress() const
    {
        return static_cast<RegisterAddress_t>( iv_address );
    }

    /** Function overloaded from parent HardwareRegister class. */
    size_t getSize() const { return 8; }

  public: // Operators

    /** @brief Equals operator. */
    bool operator==( const ScomRegister & i_r ) const
    {
        // Comparing address and chip type should be sufficient.
        return ( getAddress()  == i_r.getAddress()  ) &&
               ( getChipType() == i_r.getChipType() );
    }

    /** @brief Less than operator. */
    bool operator<( const ScomRegister & i_r ) const
    {
        // Comparing address and chip type should be sufficient.
        return (   getAddress()  <  i_r.getAddress()       ) ||
               ( ( getAddress()  == i_r.getAddress()  ) &&
                 ( getChipType() <  i_r.getChipType() )    );
    }

  private: // Instance variables

    /** This register's address. */
    const uint32_t iv_address;

}; // end class ScomRegister

/**
 * @brief A Power Systems Indirect SCOM register.
 *
 * Address width:   8 bytes
 * Register width:  2* bytes (see note below)
 * Bit order:       Ascending (0-63 left to right)
 *
 * IMPORTANT NOTE:
 *   Technically, only two bytes of data are actually used. However, the bit
 *   definition of these registers put the two bytes at the end of the returned
 *   value (bit 48-63). Therefore, this class will be made to look like the
 *   width is 8 bytes in order to make the bit indexing work in the returned
 *   BitString.
 */
class IdScomRegister : public HardwareRegister
{
  public: // Constructor, destructors, assignment, etc.

    /**
     * @brief Constructor from components.
     * @param i_chipType    Type of chip associated with this register.
     * @param i_id          Unique ID for this register.
     * @param i_instance    Instance of this register
     * @param i_accessLevel Hardware access level for this register.
     * @param i_address     An 8-byte address for this Indirect SCOM register.
     */
    IdScomRegister( ChipType_t i_chipType, RegisterId_t i_id,
                    RegisterInstance_t i_instance,
                    RegisterAccessLevel_t i_accessLevel, uint64_t i_address ) :
        HardwareRegister( i_chipType, i_id, i_instance, i_accessLevel ),
        iv_address( i_address )
    {}

    /** @brief Destructor. */
    ~IdScomRegister() = default;

  private:

    // This is needed to allow the flyweights to use the copy constructor, but
    // not allow it to be used in general.
    friend class Flyweight<IdScomRegister>;

    /**
     * @brief Copy constructor.
     *
     * Needed by Flyweight class, but should not be allowed in general.
     */
    IdScomRegister( const IdScomRegister & ) = default;

    /**
     * @brief Explicitly disables assignment operator.
     *
     * This is redundant since the compilier will implicitly delete this because
     * of the constant instance variables, but helps communicate it is not
     * allowed.
     */
    IdScomRegister & operator=( const IdScomRegister & ) = delete;

  public: // Accessor functions

    /** Function overloaded from parent HardwareRegister class. */
    RegisterType_t getRegisterType() const { return REG_TYPE_ID_SCOM; }

    /** Function overloaded from parent HardwareRegister class. */
    RegisterAddress_t getAddress() const
    {
        return static_cast<RegisterAddress_t>( iv_address );
    }

    /** Function overloaded from parent HardwareRegister class. */
    size_t getSize() const { return 8; } // See note in class documentation.

  public: // Operators

    /** @brief Equals operator. */
    bool operator==( const IdScomRegister & i_r ) const
    {
        // Comparing address and chip type should be sufficient.
        return ( getAddress()  == i_r.getAddress()  ) &&
               ( getChipType() == i_r.getChipType() );
    }

    /** @brief Less than operator. */
    bool operator<( const IdScomRegister & i_r ) const
    {
        // Comparing address and chip type should be sufficient.
        return (   getAddress()  <  i_r.getAddress()       ) ||
               ( ( getAddress()  == i_r.getAddress()  ) &&
                 ( getChipType() <  i_r.getChipType() )    );
    }

  private: // Instance variables

    /** This register's address. */
    const uint64_t iv_address;

}; // end class IdScomRegister

} // end namespace libhei

