#ifndef MISSION_DEVICES_PCDUHANDLER_H_
#define MISSION_DEVICES_PCDUHANDLER_H_

#include <devices/powerSwitcherList.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/devices/GomspaceDeviceHandler.h>
#include <fsfw/timemanager/CCSDSTime.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/datapoollocal/HasLocalDataPoolIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/objectmanager/SystemObject.h>


/**
 * @brief	The PCDUHandler provides a compact interface to handle all devices related to the
 * 			control of power. This is necessary because the fsfw manages all power related
 * 			functionalities via one power object. This includes for example the switch on and off
 * 			of devices.
 */
class PCDUHandler: public PowerSwitchIF,
        public HasLocalDataPoolIF,
        public SystemObject,
        public ExecutableObjectIF {
public:

	PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize = 20);
	virtual ~PCDUHandler();

	virtual ReturnValue_t initialize() override;
	virtual ReturnValue_t performOperation(uint8_t counter) override;
    virtual void handleChangedDataset(sid_t sid, store_address_t storeId =
            storeId::INVALID_STORE_ADDRESS);

    virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override;
	virtual void sendFuseOnCommand(uint8_t fuseNr) const override;
	virtual ReturnValue_t getSwitchState( uint8_t switchNr ) const  override;
	virtual ReturnValue_t getFuseState( uint8_t fuseNr ) const override;
	virtual uint32_t getSwitchDelayMs(void) const override;
	virtual object_id_t getObjectId() const override;
	virtual LocalDataPoolManager* getHkManagerHandle() override;

	virtual MessageQueueId_t getCommandQueue() const override;
    virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
            LocalDataPoolManager& poolManager) override;
    virtual uint32_t getPeriodicOperationFrequency() const override;
    virtual ReturnValue_t initializeAfterTaskCreation() override;
    virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
    virtual  void setTaskIF(PeriodicTaskIF* task_);

private:

    uint32_t pstIntervalMs = 0;

    /** Housekeeping manager. Handles updates of local pool variables. */
    LocalDataPoolManager poolManager;

    /**
     * The dataset holding the hk table of PDU2. This dataset is a copy of the PDU2 HK dataset
     * of the PDU2Handler. Each time the PDU2Handler updates his HK dataset, a copy is sent
     * to this object via a HousekeepingMessage.
     */
    PDU2::PDU2HkTableDataset pdu2HkTableDataset;
    /** The timeStamp of the current pdu2HkTableDataset */
    CCSDSTime::CDS_short timeStampPdu2HkDataset;

    /** Hk table dataset of PDU1 */
    PDU1::PDU1HkTableDataset pdu1HkTableDataset;
    /** The timeStamp of the current pdu1HkTableDataset */
    CCSDSTime::CDS_short timeStampPdu1HkDataset;

    uint8_t switchStates[pcduSwitches::NUMBER_OF_SWITCHES];
    /**
     * Pointer to the IPCStore.
     * This caches the pointer received from the objectManager in the constructor.
     */
    StorageManagerIF *IPCStore = nullptr;

    /**
	 * Message queue to communicate with other objetcs. Used for example to receive
	 * local pool messages from ACU, PDU1 and PDU2.
	 */
    MessageQueueIF* commandQueue = nullptr;

    size_t cmdQueueSize;

    PeriodicTaskIF* executingTask = nullptr;

    void readCommandQueue();

    /**
     * @brief   This function sets all switchStates to the initial switch configuration of the
     *          two PDUs after reboot.
     */
    void initializeSwitchStates();

    /**
     * @brief   Updates all switchStates related to the PDU2.
     *          Function is called each time a new hk dataset has been received from the PDU2Handler.
     */
    void updatePdu2SwitchStates();

    /**
     * @brief   Updates all switchStates related to the PDU1. Called each time the PDU1Handler
     *          sends a new hk dataset.
     */
    void updatePdu1SwitchStates();

    /**
     * @brief   In case of an update snapshot message this function handles the update of the
     *          local dataset.
     * @param storeId   Storage id of updated dataset.
     * @param dataset   Pointer to the local dataset.
     * @param datasetTimeStamp  Pointer to a variable which will hold the timestamp of the updated
     *                          dataset.
     */
    void updateHkTableDataset(store_address_t storeId, LocalPoolDataSetBase* dataset,
            CCSDSTime::CDS_short* datasetTimeStamp);
};

#endif /* MISSION_DEVICES_PCDUHANDLER_H_ */