/**
 * Copyright 2012 JDS Uniphase. All rights reserved.
 * CPP manager implementations
 */
#include "xtreme/cpp/cpp_manager.h"
#include <boost/foreach.hpp>
#include "xtreme/common/xtreme_types.h"
#include "xtreme/cs/cs.h"
#include "xtreme/cpp/cpp_logging.h"
#include "xtreme/cpp/internal/cpp_pipeline.h"

CPP_SYM_EL xtreme::IComponent* create_component(xtreme::cs::CS& cs) {
  CPP_LOG(INFO, "Creating CPP component...");
  return new xtreme::cpp::CPPManager(cs);
}

CPP_SYM_EL int32_t destroy_component(xtreme::IComponent* p_cpp) {
  CPP_LOG(INFO, "Destroying CPP component...");
  delete p_cpp;
  return 0;
}

namespace xtreme {

namespace cpp {

CPPManager::CPPManager(xtreme::cs::CS& cs) : cs_(cs) {
}

CPPManager::~CPPManager() {
  // Destroy CPP pipelines
  BOOST_FOREACH(CPPPipeline* p_pipeline, pipelines_) {
    if (p_pipeline != nullptr) {
      delete p_pipeline;
    }
  }
}

IPublisherList CPPManager::GetPublisherForType(const EventType& event_type) {
  CPP_LOG(INFO, "Getting publishers for " << event_type << "...");
  IPublisherList publishers;
  IPublisherList tmp;
  BOOST_FOREACH(CPPPipeline* p_pipeline, pipelines_) {
    if (nullptr != p_pipeline) {
      p_pipeline->GetPublishers(event_type, tmp);
      publishers.splice(publishers.end(), tmp);
    } else {
      CPP_LOG(ERROR, "CPP pipeline is invalid");
    }
  }
  CPP_LOG(DEBUG, publishers.size() <<
          " publishers has been found for " << event_type << ".");
  return publishers;
}

bool CPPManager::InitComponent() {
  CPP_LOG(INFO, "Initializing CPP component...");
  return true;
}

bool CPPManager::StartComponent() {
  CPP_LOG(INFO, "Starting CPP component...");

  // Construct CPP pipelines
  IPublisherList msgPublishers = cs_.GetPublisherForType(kEVENT_CP_FRAME);
  if (msgPublishers.empty()) {
    CPP_LOG(ERROR, "No CP message publishers can be found!");
    return false;
  } else {
    CPP_LOG(DEBUG, msgPublishers.size() << " CP publishers has been found.");
    BOOST_FOREACH(IPublisher* p_publisher, msgPublishers) {
      CPPPipeline* p_pipeline = new CPPPipeline(&cs_, p_publisher);
      if (nullptr == p_pipeline ||
          kCppOK != p_pipeline->Initialize()) {
        CPP_LOG(ERROR, "CPP pipeline cannot be initialized!");
        return false;
      }
      pipelines_.push_back(p_pipeline);
    }
  }

  // Start CPP pipelines
  BOOST_FOREACH(CPPPipeline* p_pipeline, pipelines_) {
    if (nullptr == p_pipeline ||
        kCppOK != p_pipeline->Start()) {
      CPP_LOG(ERROR, "CPP pipeline cannot started!");
      return false;
    }
  }

  return true;
}

bool CPPManager::StopComponent() {
  CPP_LOG(INFO, "Stopping CPP component...");
  bool ret = true;

  BOOST_FOREACH(CPPPipeline* p_pipeline, pipelines_) {
      if (nullptr == p_pipeline ||
          kCppOK != p_pipeline->Stop()) {
        CPP_LOG(ERROR, "CPP pipeline cannot be stopped!");
        ret = false;  // Need to stop all pipelines
      }
    }

  return ret;
}

}   // namespace cpp

}   // namespace xtreme
