#pragma once

namespace inertia
{

/** Enumeration for different types of ProgressUpdate(). */
enum ProgressUpdateType : unsigned
{
	PROGRESS_DOWNLOAD = 0,           ///< Progress update for flash download.
	PROGRESS_FILL_LOSS_ANALYZE = 1,  ///< Progress update for fill loss analysis.
	PROGRESS_FILL_LOSS_REQ_DATA = 2, ///< Progress update for fill loss requesting data.
	PROGRESS_FILL_LOSS_MERGE = 3,    ///< Progress update for fill loss merge.
	PROGRESS_CONVERT = 4,            ///< Progress update for converting file.
	PROGRESS_REPLAY = 5,             ///< Progress update for replaying file.
	PROGRESS_MERGE = 6,              ///< Progress update for merging files.
	PROGRESS_UPLOAD = 7              ///< Progress update for flash upload.
};


/** @brief Asynchronous callbacks
 *
 *  Class used to provide asynchronous callbacks.
 *  Extend this class and overwrite the virtual methods to receive the callbacks.
 */
struct INERTIA_API StreamListener
	: std::enable_shared_from_this<StreamListener>
{
	/** Indicate a status change (opened, closed) of the source, for example a connection or replay.
	 *  @param source the name of the source
	 *  @param isOpen true when source is opened, false when closed
	 *  @param feedback additional textual status information
	 */
	virtual void StatusUpdate(std::wstring const& source, const bool isOpen, std::wstring const& feedback) const;

	/** Callback with received processed data.
	 *  @param source the name of the source
	 *  @param addrID the applicable node
	 *  @param configs the received configurations
	 *  @param commands the received commands
	 *  @param samples the received samples
	 */
	virtual void Received(std::wstring const& source, const unsigned addrID, ConfigVectorPtr const& configs, CommandVectorPtr const& commands, SampleVectorPtr const& samples) const;

	/** Callback with received raw data.
	 *  @param source the name of the source
	 *  @param data the raw data
	 */
	virtual void Received(std::wstring const& source, std::vector<uint8_t> const& data) const;

	/** Callback when a configuration is being sent.
	 *  @param destination (e.g. serial port)
	 *  @param addrID the applicable node
	 *  @param config the configuration to send
	 */
	virtual void SendConfig(std::wstring const& destination, const unsigned addrID, ConfigPtr const& config) const;

	/** Callback when a command is being sent.
	 *  @param destination e.g. the serial device name
	 *  @param addrID the applicable node
	 *  @param command the command to send
	 */
	virtual void SendCommand(std::wstring const& destination, const unsigned addrID, CommandPtr const& command) const;

	/** Callback with progress information.
	 *  @param source the name of the source
	 *  @param addrID the applicable node
	 *  @param type the type of progress
	 *  @param count progress indicator, e.g. percentage (depends on type)
	 *  @param message textual progress message
	 */
	virtual void ProgressUpdate(std::wstring const& source, const unsigned addrID, const ProgressUpdateType type, const int count, std::wstring const& message) const;

	/** Callback with received service information.
	 *  @param source the name of the source
	 *  @param addrID the applicable node
	 *  @param response service response message
	 */
	virtual void ReceivedServiceResponse(std::wstring const& source, const unsigned addrID, ServicePtr const& response) const;

	/** Destructor */
	virtual ~StreamListener();
};

}
