/* Blinker
   Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
   a blinkenarea.org project */

#ifndef BLINKER_OUTPUT_H
#define BLINKER_OUTPUT_H

#include <string>

#include <BlinkenLib/BlinkenFrame.h>

#include "Device.h"
#include "Directory.h"
#include "File.h"
#include "InStreamFile.h"
#include "Mgrs.h"
#include "Module.h"
#include "NameFile.h"
#include "Protocol.h"
#include "ProtocolFile.h"
#include "SerCfgFile.h"
#include "StreamRecv.h"
#include "Time.h"
#include "TimeCallee.h"

namespace Blinker {

/// output of a stream to a device
class Output: public Module, public StreamRecv, public TimeCallee
{
public:
  /**
   * @brief constructor
   * @param[in] name module name
   * @param[in] mgrs managers
   * @param[in] dirBase base directory
   */
  Output(const std::string &name, Mgrs &mgrs, const Directory &dirBase);

  /// virtual destructor
  virtual ~Output();

private:
  /// copy constructor disabled
  Output(const Output &that);

  /// assignment operator disabled
  const Output & operator=(const Output &that);

public:
  /// check for update of configuration
  virtual void updateConfig();

  /**
   * @brief set current frame
   * @param[in] stream stream name
   * @param[in] pFrame current frame (NULL for none)
   */
  virtual void setFrame(const std::string &stream, stBlinkenFrame *pFrame);

  /// callback when requested time reached
  virtual void timeCall();

protected:
  /// (re-)read protocol
  void readProto();

  /// open device
  void openDevice();

  /// close device
  void closeDevice();

  /// output current frame to device
  void outputFrame();

  /**
   * @brief output frame data to device
   * @param[in] data data of one frame to output to device
   */
  void outputFrameData(const std::string &data);

  /// write data in output buffer to device
  void outputBufferedData();

  /// update time callback request
  void updateTimeCallback();

protected:
  InStreamFile m_fileInStream; ///< input stream name file
  ProtocolFile m_fileProtocol; ///< protocol file
  NameFile     m_fileDevice;   ///< name file containing name of device
  SerCfgFile   m_fileSerCfg;   ///< serial port configuration file
  Device       *m_pDevice;     ///< device to output to
  std::string  m_buffer;       ///< buffered data still to be output to device
  bool         m_dropped;      ///< if the last frame has been dropped
}; // class Output

} // namespace Blinker

#endif // #ifndef BLINKER_OUTPUT_H

