#pragma once
#include "../Utils/Process/ProcessContainer.h"
#include "InactiveLayer1.h"
#include "InactiveLayer2.h"
#include "InactiveLayer3.h"
#include "InactiveLayer4.h"

/**
 * @brief Scenario base class.
 */
template <class Derived>
class Scenario : public Process
{
public:
  Scenario()
    : Process(NULL)
    , m_sparStartedEventHandler(*this)
    , m_sparEndedEventHandler(*this)
    , m_timerEvent(*this, 100, 0, 0)
  {
    zombifyOnTerminate();
    Process::start();
  }

  template <class SparAIFactory>
  SparAIContainer* instantiateSparAI(SparAIFactory& factory)
  {
    m_spar = static_cast<Derived*>(this)->instantiateSparAIImpl(factory);
    m_spar->getStartEvent().subscribe(&m_sparStartedEventHandler, NULL);
    m_spar->getTerminateEvent().subscribe(&m_sparEndedEventHandler, NULL);
    return m_spar;
  }

protected:

  virtual void onSparStarted(void*)
  {
  }

  virtual void onSparEnded(void*)
  {
    terminate(Success);
  }

  SparAIContainer* m_spar;

private:
  void onBeforeSparStarted(void*)
  {
    // Make sure the callback onSparStarted() takes place after the units are initialized
    m_timerEvent.activate();
  }

  void onTimer()
  {
    onSparStarted(NULL);
  }

  SCHEDULER_EVENT_HANDLER(Scenario, onTimer) m_timerEvent;
  EVENT_HANDLER(Scenario, onBeforeSparStarted) m_sparStartedEventHandler;
  EVENT_HANDLER(Scenario, onSparEnded) m_sparEndedEventHandler;
};
