//decentralized scheduling using customized schedule type to
//randomize events that arrive on the scheduling mechanism for the same time.

#import <simtools.h>
#import <analysis.h>
#import <defobj/Create.h>
#import <objectbase.h>
#import <simtoolsgui/GUISwarm.h>
#import <objectbase/Swarm.h>
#import <random.h>


@interface Bug: Swarm
{
  id schedule;
}

- buildActions;
- activateIn: swarmContext;
- scheduleSelfAt: (int) x;

@end

@implementation Bug


-scheduleSelfAt: (int) x
{
  [schedule at: x createActionTo: self message: M(step)];
  return self;
}

- buildActions
{
  [super buildActions];

  schedule= [Schedule createBegin: self];
  [schedule setAutoDrop: 1];
  schedule = [schedule createEnd];

  [schedule at: 0 createActionTo: self message: M(step)];
  
  return self;
}

- activateIn: swarmContext
{
  printf("bug schedule activated \n");
   [super activateIn: swarmContext];
   [schedule activateIn: self ];
   return [self getActivity]; 
}


@end

@interface BugA: Bug
{

}
-step;

@end

@implementation BugA

-step
{
  printf("I'm bugA, and the current time is %d \n",getCurrentTime());
  [self scheduleSelfAt: getCurrentTime()+1];

  return self;
}


@interface BugB: Bug
{
}
-step;

@end

@implementation BugB

-step
{
  printf("I'm bugB, and the current time is %d \n",getCurrentTime());
  [self scheduleSelfAt: getCurrentTime()+5];
  return self;
}


@interface ModelSwarm: Swarm
{
  id <Schedule> schedule;
  id  bugA, bugB;
}
- announcement;
- buildObjects;
- buildActions;
- activateIn: swarmContext;

@end

@implementation ModelSwarm

-announcement
{
  printf("I'm model swarm, current time is %d \n",getCurrentTime());
  return self;
}
-buildObjects
{
 
  bugA=[BugA create: self];
  bugB=[BugB create: self];

  [bugA buildObjects];
  [bugB buildObjects];

  return self;
}


- buildActions
{
  [super buildActions];
  [bugA buildActions];
 
  [bugB buildActions];

  schedule = [Schedule createBegin: self];
  //[schedule setAutoDrop: 1];
  [schedule setRepeatInterval: 1];
  schedule = [schedule createEnd];
  
  [schedule at: 0 createActionTo: self message:M(announcement)];
  
  printf("stop Sch \n");

  return self;
}

- activateIn: swarmContext
{
  xprint(self);
  [super activateIn: swarmContext];
  [bugA activateIn: self];
  [bugB activateIn: self];
  [schedule activateIn: self];
  return [self getActivity];
}  
@end




@interface ObserverSwarm: GUISwarm
{
  id modelSwarm;
}
+createBegin: aZone;
-buildObjects;
-buildActions;
-activateIn: aZone;
@end

@implementation ObserverSwarm

+createbegin: aZone
{
  return [super createBegin: aZone];  
}

-buildObjects
{
  id groupProto; id syncScheduleProto;

  [super buildObjects]; 


   groupProto=[ConcurrentGroup customizeBegin: self];
   [groupProto setDefaultOrder: Randomized];
   // [groupProto setDefaultOrder: Sequential];
   groupProto = [groupProto customizeEnd];

   syncScheduleProto = [Schedule customizeBegin: self];
   [syncScheduleProto setConcurrentGroupType: groupProto];
   [syncScheduleProto setAutoDrop: 1];
   syncScheduleProto = [syncScheduleProto customizeEnd];

   modelSwarm = [ModelSwarm createBegin: self];
   [modelSwarm setSynchronizationType: syncScheduleProto ];
   modelSwarm = [modelSwarm createEnd];


   // modelSwarm=[ModelSwarm create: self];
  [controlPanel setStateStopped];
  [modelSwarm buildObjects];
  return self;
}  
-buildActions
{
  [super buildActions];
  [modelSwarm buildActions];
  return self;
}

-activateIn: aZone
{
  [super activateIn: aZone];
  [modelSwarm activateIn: self];
    return [self getActivity];
}


int
main (int argc, const char **argv)
{
  id swarm;

  initSwarm (argc, argv);

  swarm = [ObserverSwarm create: globalZone];

  [swarm buildObjects];
  [swarm buildActions];
  [swarm activateIn: nil];
  [swarm go];
  
  return 0;
}

/* 
Local Variables: 
compile-command: "$SWARMHOME/bin/libtool-swarm --mode=link gcc -D_GNU_SOURCE -o pjrepeater  -g -Wno-import \
-I$SWARMHOME/include -I$SWARMHOME/include/swarm -L$SWARMHOME/lib \
-L$SWARMHOME/lib/swarm pjrepeater3.m  -lswarm -lobjc " 
End: 
*/






