#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
Commander g_commander[NUMBER_OF_ROBOTS];
//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
//Broadcaster g_broadcaster[NUMBER_OF_ROBOTS];
int main(void)
{

#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;
  Compass* compass;

  drive = Drive::getDrive();
  psds = PSDs::getPSDs();
  camera = Camera::getCamera();
  radio = Radio::getRadio();
  compass = Compass::getCompass();

  drive->initialize();
  psds->initialize();
  camera->initialize();
  radio->initialize();
  compass->initialize();
#endif

  //SIR is a singleton class, the only instance is created
  //in SIR.cpp using ("sir", 256*1024, MAX_PRI, 0)
  SIR* sir = SIR::getSIR();
  sir->initialize();

  UI ui("ui", 128*1024, MIN_PRI, 3);
  ui.initialize();

  OSMTInit(PREEMPT); //prepare for preemptive multi-tasking

  //initialize global threads
  g_commander[OSMachineID()].initialize();
  
  //create threads
  sir->spawn();
  g_commander[OSMachineID()].spawn();
  ui.spawn();

  //set thread for user interface as ready for execution
  ui.ready();
  
  OSPermit(); //activate preemptive multitasking

  OSWait(100); //necessary for startup

// -----------------------------------------------------------------------
// processing will return HERE when there is no READY thread left
  return 0;
}
