/* 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 <BlinkenLib/BlinkenFrame.h>

#include "Directory.h"
#include "File.h"
#include "InStreamFile.h"
#include "Priority.h"
#include "PriorityInput.h"
#include "StreamMgr.h"
#include "StreamRecv.h"

namespace Blinker {

/**
 * @brief constructor
 * @param[in] priority owning priority based selector
 * @param[in] name name of input (i.e. priority)
 * @param[in] dirBase base directory
 */
Priority::Input::Input(Priority &priority, const std::string &name,
                       const Directory &dirBase):
  m_priority(priority),
  m_name(name),
  m_fileInStream(dirBase.getFile("instream"), priority.m_mgrs.m_streamMgr),
  m_pFrame(NULL)
{
  // set up
  m_fileInStream.setStreamRecv(this);
}

/// virtual destructor
Priority::Input::~Input()
{
  // clean up
  m_fileInStream.setStreamRecv(NULL);
}

/// check for update of configuration
void Priority::Input::updateConfig()
{
  // input stream name file was modified -> re-get input stream
  if (m_fileInStream.checkModified()) {
    frame(NULL); // unset frame to force priority reevalulation
    m_fileInStream.update();
  }
}

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

/**
 * @brief get current frame
 * @return current frame (NULL if none)
 */
stBlinkenFrame * Priority::Input::getCurFrame()
{
  return m_pFrame;
}

/**
 * @brief set current frame
 * @param[in] pFrame current frame (NULL for none)
 */
void Priority::Input::frame(stBlinkenFrame *pFrame)
{
  // save new frame
  m_pFrame = pFrame;

  // there is a frame now
  if (pFrame) {

    // if we are current input
    if (m_priority.m_itCurIn != m_priority.m_inListTracker.m_list.rend() &&
        m_priority.m_itCurIn->m_pObj == this)
      // pass on frame
      m_priority.m_fileOutStream.setFrame(pFrame);

    // we have a higher priority than current input
    if (m_priority.m_itCurIn == m_priority.m_inListTracker.m_list.rend() ||
        m_priority.m_itCurIn->m_name < m_name)
      // tell priority based selector to select us as input
      m_priority.select(this);

  }
  // there is no frame
  else {

    // if we are current input
    if (m_priority.m_itCurIn != m_priority.m_inListTracker.m_list.rend() &&
        m_priority.m_itCurIn->m_pObj == this)
      // tell priority based selector to select lower priority input
      m_priority.selectLower();

  }
}

} // namespace Blinker

