#include "UI.h"
#include "Commander.h"
#include "SIR.h"
#include "Broadcaster.h"
#include "Version.h"

#include "CubeClustering.h"

//the Commander is global because:
//all threads must be spawn in main (before the multi-tasking is activated)
//so our Commander must be spawn in main
//but then Starter needs access to this Commander
//so we declared the commander as global
//if (one day ;-) threads can be spawn during runtime
//then the Commander can be created locally in Starter
//and does not need to be a pointer to the global instance
//anymore
//the parameters are: name, stack size, priority, unique id
Commander g_commander("commander", 128*1024, MAX_PRI, 1);
//the Broadcaster is global because:
//all threads must be spawn in main (before the multi-tasking is activated)
//so our Broadcaster must be spawn in main
//but then Starter needs access to this Broadcaster
//so we declared the broadcaster as global
//if (one day ;-) threads can be spawn during runtime
//then the Broadcaster can be created locally in Starter
//and does not need to be a pointer to the global instance
//anymore
//the parameters are: name, stack size, priority, unique id
Broadcaster g_broadcaster("broadcaster", 128*1024, MIN_PRI, 2);
int main(void)
{
  //SIR is a singleton class, the only instance is created
  //in SIR.cpp using ("sir", 256*1024, MAX_PRI, 0)
  SIR* sir = SIR::getSIR();

  UI ui("ui", 128*1024, MIN_PRI, 3);

  OSMTInit(PREEMPT); //prepare for preemptive multi-tasking

  //create threads
  sir->spawn();
  g_commander.spawn();
  g_broadcaster.spawn();
  ui.spawn();

  //set thread for user interface as ready for execution
  ui.ready();

#ifdef EYESIM_CUBECLUSTERING_PARAMETERS
  //to run the program on the EyeSim simulator the initialization of Drive, PSDs,
  //Camera and Radio must not take place in the constructor as the EyeSim simulator
  //is not able to execute RoBIOS library functions in class constructors.
  //so we have to declare the initialize method as public and call it in main before
  //we start the program
  //if running the program on real robots the initialization must be done in the
  //constructors (otherwise the camera initialization doesn't work, for example
  //(for whatever reason)
  Drive* drive;
  PSDs* psds;
  Camera* camera;
  //Radio* radio;

  drive = Drive::getDrive();
  psds = PSDs::getPSDs();
  camera = Camera::getCamera();
  //radio = Radio::getRadio();

  drive->initialize();
  psds->initialize();
  camera->initialize();
  //radio->initialize();
#endif

  OSPermit(); //activate preemptive multitasking

  OSWait(100); //necessary for startup

// -----------------------------------------------------------------------
// processing will return HERE when there is no READY thread left
  return 0;
}
