/**
 * Implements mind_kernel.hh for an Eyebot platform.
 *
 * If preprocessor variable REACT is defined then
 * a strictly reactive agent is built (i.e. only the
 * Id process is activated)
 */

#ifdef EYEBOT

#include "mind_kernel.hh"

// If not a purely reactive agent, then create thread processes
#ifndef REACT

#include "kern.h"

#define SSIZE  8192     //Size of thread stack

tcb *id_p;       ///< id process
tcb *ego_p;      ///< ego process
tcb *master_p;   ///< master process

sem stack_s;        ///< stack semaphore


void Master()
{
  while(myId.Active())
    {
       OSReschedule(); // yield control to other processes
    }

  // done with program
  OSKill(id_p);
  OSKill(ego_p);
  OSKill(0);
}


void Think(void)
{
	while (1)
	{
		if(myEgo.Active())
		{
			myEgo.Think();
			OSReschedule();
		}
	}
}


void Act(void)
{
	while (1)
	{
		if(myId.Active())
		{
			myId.ExciteBehaviors();
			OSReschedule();
		}
    }
}
#endif

int main(int argc, char *argv[])
{
#ifndef REACT
	/* Initialize Multithreading */
	LCDPrintf("Kernel.. ");
	OSMTInit(COOP);
	LCDPrintf("ok\n");


	/* Initialize semaphores */
	LCDPrintf("Semaphore..");
	//OSSemInit(&ego_s,0);
	OSSemInit(&stack_s,0);
	LCDPrintf("ok\n");

	/* Initialize threads */
	LCDPrintf("Id...");
	id_p = OSSpawn("id_p", Act, SSIZE, MIN_PRI,1);
	if(!id_p) OSPanic("failed");
	LCDPrintf("ok\n");

	LCDPrintf("Ego...");
	ego_p = OSSpawn("ego_p", Think, SSIZE, MIN_PRI,2);
	if(!ego_p) OSPanic("failed");
	LCDPrintf("ok\n");

	LCDPrintf("Master...");
	master_p = OSSpawn("master", Master, SSIZE, MIN_PRI,3);
	if(!master_p) OSPanic("failed");
	LCDPrintf("ok\n");

	OSWait(100);
	LCDClear();


	/* Ready the mind */
	myId.Ready();
	myEgo.Ready();
	mySuperEgo.Ready();
	LCDClear();


	/* READY all threads and start multitasking */
	OSReady(id_p);
	OSReady(ego_p);
	OSReady(master_p);

	/* Activate preemptive multitasking */
	OSPermit();
	OSReschedule();
#endif

	// If purely reactive, then don't need threads only single loop
#ifdef REACT
	myId.Ready();
	LCDClear();
	while(myId.Active())
	{
		myId.ExciteBehaviors();
	}
#endif

	/* All done */
	LCDClear();

	return 0;
}

#endif //EYEBOT
