#import "grid.h"
#import <activity.h>
#import <activity/GenericSwarm.h>

#define __USE_FIXED_PROTOTYPES__   // for gcc headers
#include <stdio.h>

static void testTerminate( timeval_t terminateTime )
{
  if ( getCurrentTime() >= terminateTime )
    [getTopLevelActivity() terminate];
}

static void stopCurrent( void )
{
  [getCurrentActivity() stop];
}

@interface MySwarm : GenericSwarm_c
{
  int  myVar;
}
- (void) setMyVar: (int)value;
- (void) printMyVar;
@end

@implementation MySwarm

- (void) setMyVar: (int)value
{
  myVar = value;
}

- (void) printMyVar
{
  printf( "value is %d\n", myVar );
}

@end

int main(void)
{
  id   aZone, aTurtle;
  id   simSched1, action1, action2, action3, moveGroup;
  id   simSched2, displaySchedule, terminateSchedule;
  id   simSwarm, swarm, swarmActivity;
  int  nextCount;

  // initialize

  initModule( grid );
  initModule( activity );
  aZone = [Zone create: globalZone];

  // create a turtle to turn and move during simulation

  aTurtle = [GridTurtle create: aZone];

  // create a pair of simulation schedules (repeat intervals of 2 and 4)

  simSched1 = [Schedule createBegin: aZone];
  [simSched1 setRepeatInterval: 2];
  simSched1 = [simSched1 createEnd];
  action1 = [simSched1 at: 0 createActionTo: aTurtle message: M(move:):(id)10];
  moveGroup = [ActionGroup create: aZone];
  action2 = [moveGroup createActionTo: aTurtle message: M(move:) : (id)-5];
  [simSched1 at: 0 createAction: moveGroup];
  [simSched1 at: 0 createActionCall: (func_t)testTerminate : (id)20];

  simSched2 = [Schedule createBegin: aZone];
  [simSched2 setRepeatInterval: 4];
  simSched2 = [simSched2 createEnd];
  [simSched2 at: 0 createActionTo: aTurtle message: M(turn:) : (id)1];
  action3 = [simSched2 at: 0 createActionCall: (func_t)testTerminate : (id)10];

  // create a display schedule to print turtle at every time step

  displaySchedule = [Schedule createBegin: aZone];
  [displaySchedule setRepeatInterval: 1];
  displaySchedule = [displaySchedule createEnd];
  [displaySchedule at: 0 createActionTo: aTurtle message: M(print)];
  [displaySchedule at: 0 createActionCall: (func_t)testTerminate : (id)50];

  // create a schedule to terminate all activity at timestep 32

  terminateSchedule = [Schedule create: aZone];
  [terminateSchedule at: 10
    createActionTo: moveGroup message: M(remove:) : action2];
  [terminateSchedule at: 4
    createActionTo: simSched2 message: M(remove:) : action3];
  [terminateSchedule at: 32 createActionCall: (func_t)testTerminate : (id)32];

  // create and activate display swarm

  swarm = [GenericSwarm create: aZone];
  swarmActivity = [swarm activateIn: nil];

  // create simulation swarm from custom subclass

  simSwarm = [MySwarm create: aZone];
  [simSwarm setMyVar: 99];
  [simSwarm printMyVar];
  [simSwarm activateIn: swarm];
  [[[simSwarm getSwarmActivity] getSwarm] printMyVar];

  // activate display schedules now that simulation swarm already activated

  [displaySchedule activateIn: swarm];
  [terminateSchedule activateIn: swarm];

  // activate simulation swarm in display swarm

  [simSched1 activateIn: simSwarm];
  [simSched2 activateIn: simSwarm];

  // run the swarm to completion

  // [swarmActivity run];
  for ( nextCount = 1; [swarmActivity next] == Stopped; nextCount++ );
  printf( "number of next calls: %d\n", nextCount );
  return 0;
}
