/******************************
map_control.c

This code illustrates how to "wrap" an application written in C, to be
an OAA agent.  This shows the sort of code needed to allow the agent
to provide a service (or "solvable", in OAA parlance).  We imagine
that this agent controls a map display, and the service provided:

    pan(Direction, Distance, PreviousLocation)

shifts the center of the display in the direction (0 - 360 degrees)
given by Direction.  Distance is a real number (kilometers), the
distance to be shifted, and PreviousLocation is a return argument, to
be given as loc(X,Y), indicating the previous location on which the
map was centered.

We assume, for this example, a pre-existing API function of the map
display code, in C, that implements this capability:

    int app_pan(int Direction, double Distance, AppLocation *PrevLocation);

Communications between OAA agents are conducted using requests (goals)
expressed in the Interagent Communication Language (ICL), the syntax
of which is the same as Prolog syntax.  A goal will arrive looking
like this, for example:

    pan(270, 2, PrevLoc) % PrevLoc is an ICL "variable"

The job of the agent wrapper code is to handle an incoming goal, by
calling the appropriate API function, and then to construct one or
more "solutions" for that goal.  (In this example, only a single
solution is called for).  Each solution looks like the goal, except
that the return argument (PrevLoc) is replaced by the appropriate
return values.  For example, a solution might look like this:

    pan(270, 2, loc(43, 78))

*******************************

This sample code shows only how an agent provides a solvable, and does
not illustrate how an agent requests the use of other agents'
solvables (although that can be done very simply).  Also, it should be
noted that the OAA libraries support several other interesting classes
of capabilities, such as data management and triggers, which are not
illustrated here.

Disclaimer: This code is for illustrative and tutorial purposes.  It
hasn't been compiled, and may contain minor errors.

*******************************/

/* Include the OAA C library */
#include <libicl.h>
#include <liboaa.h>
#include <stdio.h>
#include <application_code.h> /* declares function app_pan */

/* Callback function for the pan3 solvable.  This function will be
 * called from OAA library code, when a pan/3 goal is received from
 * the facilitator to which this agent is connected.  
 *
 * This function handles pan/3 incoming goals, such as:
 *    pan(270, [distance(2)], PrevLoc) 
 */
int pan3_Callback(ICLTerm* goal, ICLTerm* params, ICLTerm* solutions) {
  iclTerm *GoalArg1, *GoalArg2, *SolutionArg3;
  iclTerm *Solution;
  int Direction;
  double Distance;
  AppLocation *PrevLocation;

  /* Extract the input arguments */
  GoalArg1 = icl_NthTerm(goal, 1);
  GoalArg2 = icl_NthTerm(goal, 2);
  Direction = icl_Int(GoalArg1);
  Distance = icl_Float(GoalArg2);

  /* Call the appropriate application API function */
  app_pan(Direction, Distance, PrevLocation);

  /* Construct the solution term */
  SolutionArg3 = icl_NewStruct("loc", 2, PrevLocation.x, PrevLocation.y);
  Solution = icl_NewStruct("pan", 3, GoalArg1, GoalArg2, SolutionArg3);

  /* and add it to the return argument of this function */
  icl_AddToList(solutions, Solution, TRUE);

  /* OAA library code then takes care of routing the solutions back to
     the requesting agent */

  return FALSE;
}

/*
 * Connect to an OAA facilitator, and register the pan/3 solvable.
 */
int setup_oaa_connection(int argc, char *argv[]) {
  ICLTerm* mySolvablesAsTerm = icl_NewList(NULL);
  icl_AddToList(mySolvablesAsTerm, 
    icl_NewTermFromString(
      "solvable(pan(Direction, Distance, PreviousLocation),
       [callback(pan3)])"),
    TRUE);

  if (com_Connect("parent", ICL_VAR)<0) {
    printf("Could not connect\n");
    return FALSE;
  }
    
  if (!oaa_Register("parent", "simple_agent_c", mySolvablesAsTerm)) {
    printf("Could not register\n");
    return FALSE;
  }

  if (!oaa_RegisterCallback("pan3", pan3_Callback)) {
    printf("Could not register pan3 callback\n");
    return FALSE;
  }

  icl_Free(mySolvablesAsTerm);

  oaa_MainLoop(TRUE);
}


int main(int argc, char *argv[])
{
  setup_oaa_connection(argc, argv);
}



