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

#include <string>

#include "File.h"
#include "InSyncFile.h"
#include "Mgrs.h"
#include "Module.h"
#include "OutSyncFile.h"
#include "SyncNameSplitter.h"
#include "SyncRecv.h"

namespace Blinker {

/**
 * @brief constructor
 * @param[in] name module name
 * @param[in] mgrs managers
 * @param[in] dirBase base directory
 */
SyncNameSplitter::SyncNameSplitter(const std::string &name, Mgrs &mgrs, const Directory &dirBase):
  Module(name, mgrs, dirBase),
  m_fileInSync(dirBase.getFile("insync"), mgrs.m_syncMgr),
  m_fileDelimiter(dirBase.getFile("delimiter")),
  m_fileFieldNo(dirBase.getFile("fieldno")),
  m_fileOutSync(dirBase.getFile("outsync"), mgrs.m_syncMgr)
{
  // init
  m_fileInSync.setSyncRecv(this);
}

/// virtual destructor
SyncNameSplitter::~SyncNameSplitter()
{
  // cleanup
  m_fileInSync.setSyncRecv(NULL);
}

/// check for update of configuration
void SyncNameSplitter::updateConfig()
{
  // input sync stream name file was modified -> re-get input sync stream
  if (m_fileInSync.checkModified())
    m_fileInSync.update();

  // delimiter file was modified -> re-get delimiter
  if (m_fileDelimiter.checkModified())
    m_fileDelimiter.update();

  // filed number file was modified -> re-get filed number
  if (m_fileFieldNo.checkModified())
    m_fileFieldNo.update();

  // output sync stream name file was modified -> re-get output sync stream
  if (m_fileOutSync.checkModified())
    m_fileOutSync.update();
}

/**
 * @brief send synchronization information
 * @param[in] sync sync stream name
 * @param[in] pInfo synchronization information
 */
void SyncNameSplitter::sendInfo(const std::string &sync, Info &info)
{

  // pass on unmodified sync information if delimiter or field number invalid
  if (! m_fileDelimiter.m_valid || ! m_fileFieldNo.m_valid) {
    m_fileOutSync.sendInfo(info);
    return;
  }

  // split name
  const std::string &delim = m_fileDelimiter.m_obj.m_str;
  unsigned int fieldNo = m_fileFieldNo.m_obj.m_uint;
  std::string::size_type pos = 0;
  unsigned int field = 0;
  std::string splitname;
  while (pos < info.name.length()) {
    std::string::size_type found = info.name.find(delim, pos);
    if (found == std::string::npos) {
      found = info.name.length();
    }
    if (field == fieldNo) {
      splitname = info.name.substr(pos, found - pos);
      break;
    }
    pos = found + delim.length();
    ++field;
  }

  // pass on sync information with split name
  Info splitinfo = info;
  splitinfo.name = splitname;
  m_fileOutSync.sendInfo(splitinfo);

  (void)sync; // unused
}

} // namespace Blinker

