/**
* @file ISAlgorithm.cpp
* @author Dan Saunders & Mathieu Labare, on behalf of the SoLid collaboration.
* @date 16 Feb 2016
*/

#include "ISAlgorithm.h"

//==============================================================================

//! Constructor just setting passed values.
ISAlgorithm::ISAlgorithm(SDetector * dtr, SClipboard * cb, std::string name) : 
  m_detector(dtr),
  m_clipboard(cb),
  m_name(name),
  m_runStopped(false)
{}


//==============================================================================

ISAlgorithm::~ISAlgorithm() {}


//==============================================================================

//! Wrapper function for SAlgorithm initialize - calls derived initialize.
/* Currently only perfoms eshetics and prepares for performance measurements.
 */
void ISAlgorithm::parentInitialize() {
  std::cout<<"-------"<<std::endl;
  std::cout<<"[Note]: Initializer of: "<<name()<<std::endl;
  std::string histoName = name() + "_CycleExecutionTime";
  std::string histoTitle = name() + "_CycleExecutionTime; Time (ms); N";
  h_cycleExecutionTime = new TH1F(histoName.c_str(), histoTitle.c_str(), 1000, 0, 10000);
  cb()->histosFile()->mkdir(name().c_str());
  initialize();
}


//==============================================================================

//! Wrapper function for SAlgorithm execute. 
/* Times and plots each execution, except for the first cycle execute, since
 * often extra overhead performed. 
 */
void ISAlgorithm::parentExecute() {
  // Timing stuff.
  struct timeval  tv1, tv2;
  gettimeofday(&tv1, NULL);

  execute();

  // Timing stuff.
  gettimeofday(&tv2, NULL);
  double timeElapsed = (unsigned long long) (tv2.tv_usec - tv1.tv_usec)
                       + (unsigned long long) ((tv2.tv_sec - tv1.tv_sec)*1000000ULL);
  if (cb()->cycle() > 1) h_cycleExecutionTime->Fill(timeElapsed);
}


//==============================================================================

//! Wrapper function for SAlgorithm finalize. 
/*! Cd's into output histo file and creates folder with this algo's name.
 * Execution time histos and stored separatly, all together. 
 */
void ISAlgorithm::parentFinalize() {
  std::cout<<"-------"<<std::endl;
  std::cout<<"[Note]: Finalizer of: "<<name()<<std::endl;
  cb()->histosFile()->cd(name().c_str());
  finalize();
}


//==============================================================================

//! Creates a 1d histogram for each channel.
std::vector<TH1D*> * ISAlgorithm::initPerChannelPlots1D(std::string name,
    std::string title, unsigned int nBins, double xLow, double xUp) 
{
  std::vector<TH1D*> * plots = new std::vector<TH1D*>();
  for (uint i=0; i<dtr()->nChannels(); i++) {
    std::string plotName =  "safChan" + std::to_string(i) + "_" + name;
    std::string plotTitle = "SChannel "+ std::to_string(i) + ": " + title;
    TH1D * plot = new TH1D(plotName.c_str(), plotTitle.c_str(), nBins, xLow, xUp);
    plots->push_back(plot);
  }
  return plots;
}


//==============================================================================

//! Returns a successful status for an SRunStatus. 
/*! Trivial since it just uses the default constructor, but its worth to be 
 * explcit for users.
 */
SRunStatus * ISAlgorithm::successfulRunStatus() 
{
  return new SRunStatus();
}


//==============================================================================