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

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

static BOOL trace( id anActivity );

int main(void)
{
  id   aZone, aList, aTurtle;
  id   emptyActions, moveActions, printActions, moveAndPrint;
  id   groupActivity, swarm, swarmActivity, status;
  int  i, stepCount;

  initModule( grid );
  initModule( activity );

  aZone = [Zone create: globalZone];
  aList = [List create: aZone];

  for ( i = 0; i < 10; i++ ) {
    aTurtle = [GridTurtle create: aZone];
    [aTurtle turn: -1];
    [aTurtle move: i * 10];
    [aTurtle turn: 1];
    [aList addLast: aTurtle];
  }

  emptyActions = [ActionGroup create: aZone];

  moveActions = [ActionGroup create: aZone];
  for ( i = 0; i < 10; i++ ) {
    if ( i % 2 )
      [moveActions
        createActionTo: [aList atOffset: i] message: M(move:) : (id)10 ];
  }

  printActions = [ActionGroup create: aZone];
  for ( i = 0; i < 10; i++ ) {
    [printActions createActionTo: [aList atOffset: i] message: M(print)];
  }

  moveAndPrint = [ActionGroup create: aZone];
  [moveAndPrint createAction: emptyActions];
  [moveAndPrint createAction: moveActions];
  [moveAndPrint createAction: printActions];
  for ( i = 0; i < 10; i++ ) {
    if ( i % 2 )
      [moveAndPrint
        createActionTo: [aList atOffset: i] message: M(move:) : (id)10];
  }
  [moveAndPrint createActionForEach: aList message: M(print)];

  groupActivity = [moveAndPrint activateIn: nil];
  while ( (status = [groupActivity run]) != Completed );
  printf( "run return status: %s\n\n", [status getName] );
  [groupActivity drop];

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

  if ( swarmActivity != [swarm getSwarmActivity] )
    raiseEvent( WarningMessage, nil );

  for ( stepCount = 1; [swarmActivity step] == Stopped; stepCount++ );
  printf( "number of steps: %d\n", stepCount );

  // while ( (status = [swarmActivity run]) != Completed );
  // printf( "run return status: %s\n\n", [status getName] );

  _activity_trace = trace;
  return 0;
}

static BOOL trace( id anActivity )
{
  if ( [anActivity getCurrentAction] )
    printf( "action trace: %s\n",
      [[[anActivity getCurrentAction] createIDString: scratchZone] getC] );
  else
    printf( "action trace: activity status %s\n",
      [[anActivity getStatus] getName] );

  return 0;
}
