//Adapted from "PermutedIndex" by Marcus Daniels, swarm-support, June 21, 2000

#import <simtools.h> // initSwarm
#import <collections.h> // Array
#import <defobj/Create.h> // CreateDrop
#import <objectbase/Swarm.h> // Swarm
#import <defobj/defalloc.h> // getZone

#include <misc/avl.h> //for the AVLtree


#define COUNT 10

@interface Agent: CreateDrop
{
  id <Array> population;
  unsigned personalNumber;
}
+ create: (id <Zone>)aZone setPopulation: (id <Array>)thePopulation setPIN: (unsigned)pin;

- print;

- (void)permutePopulation;

- (int) getPIN;

@end

@implementation Agent
+ create: (id <Zone>)aZone setPopulation: (id <Array>)thePopulation setPIN: (unsigned)pin
{
  Agent *obj = [self createBegin: aZone];
  obj->population = thePopulation;
  obj->personalNumber = pin;
  return [obj createEnd];
}

- print
{

  printf("Agent %d \n",personalNumber);
  return self;
}


- (void)permutePopulation
{
  id <Index> index = [population beginPermuted: getZone (self)];
  id member;

  printf ("Agent: %u sees permutation:", personalNumber);
  for (member = [index next]; [index getLoc] == Member; member = [index next])
    printf (" %u", [member getPIN]);
  printf ("\n");
  [index drop];
}

- (int) getPIN
{
  return personalNumber;
}

@end

@interface ModelSwarm: Swarm
{
  id <Array> population;
   avl_tree *myTree1;
  avl_tree *myTree2;

}
- buildObjects;
@end

@implementation ModelSwarm

static int
compare_agent_ids (const void *A, const void *B, void *PARAM)
{
  id a = (id) A;
  id b = (id) B;

  if (a  < b )
    return -1;

  return a > b;
}

static int
compare_agent_position (const void *A, const void *B, void *PARAM)
{
  int a =  [(const id) A getPIN];
  int b =  [(const id) B getPIN];
  if (a  < b )
    return -1;

  return a> b;
}

static void
print_node ( void *A, void *PARAM)
{
  id a = (id) A;
  [a print];
}


- buildObjects
{
  unsigned i;
  id anAgent;

  [super buildObjects];
  population = [Array create: globalZone setCount: COUNT];

  myTree1=avl_create (compare_agent_position, NULL);

  myTree2=avl_create (compare_agent_ids, NULL);

  for (i = 0; i < COUNT; i++)
    {
      anAgent= [Agent create: self setPopulation: population setPIN: i];
      [population atOffset: i put: anAgent];

      avl_probe(myTree1, anAgent );//uses integer keys;

      avl_probe(myTree2, anAgent);//retrieves node or inserts if key not in tree already
    }	                         //this amounts to a "set"

  
   return self;
}

- (void)test
{
  int i;
  //  int j;
  id anAgent=nil;

  printf("Now, use the avl_walk to march through the tree1\n");
  printf("This is supposed to start with the smallest key and move on up.");


  avl_walk(myTree1 , print_node, NULL);

  anAgent = nil;
  printf("Now, go forwards through the tree1 with a for loop that uses   \n");
  printf("avl_find with the value of the agent itself from [population atOffset:i] as the key  \n");

  for (i = 0; i< COUNT; i++)
    {
      id outputAgent=nil;
      anAgent =  [population atOffset: i];
      outputAgent= avl_find (myTree2, anAgent);
      [outputAgent print];
    }


  printf("Now, go backwards through the tree2 with a for loop that uses  \n");
  printf("avl_find with the value of the agent itself as the key  \n");

  for (i = 0; i< COUNT; i++)
    {
      id outputAgent = nil;
      anAgent = [population atOffset: COUNT-i-1];
      outputAgent = avl_find ( myTree2, anAgent );
      [outputAgent print];
    }

  anAgent = nil;
  printf("Now, grab the agent 5th from the tree2 by asking for it by name \n");
  anAgent = avl_find (myTree2, [population atOffset: 4]);
  [anAgent print];

 

  printf ("Now, grab the agent 5th from the tree1 by asking for it by name \n");
  anAgent=nil;
  
  anAgent = avl_find (myTree1, [population atOffset: 4] );
  [anAgent print];

}
@end

int
main (int argc, const char **argv)
{
  initSwarmBatch (argc, argv);
  
  {
    id modelSwarm = [ModelSwarm create: globalZone];

    [modelSwarm buildObjects];
    [modelSwarm test];
  }
  return 0;
}

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

