/* Copyright (c) 2001-2004 by SoftIntegration, Inc. All Rights Reserved */
#include <stdio.h>
#include <ch.h>

typedef int(*funcHandle)(void *);
int setHandle(int index, funcHandle funptr, void *usrMsg);
void callFun(int index);
static ChInterp_t interp;
static int chdl_funarg(void *usrMsg);

struct HandlePairs{
        int num;
        funcHandle handle_ch;
        void *usrMsg;
};

/* keep pairs of index, handler and message */
#define MAXNUM_P 3 /* greater than or equal the number of the event */
static struct HandlePairs handlePairs[MAXNUM_P];  
static int index_p = 0;   /* index of handlePairs, from 0 to MAXNUM_P-1 */


EXPORTCH int setHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int index;
  funcHandle handle_ch;
  void *usrMsg;
  int retval;

  Ch_VaStart(interp, ap, varg);
  index = Ch_VaArg(interp, ap, int);
  handle_ch = Ch_VaArg(interp, ap, funcHandle);
  usrMsg = Ch_VaArg(interp, ap, void *);

  if(index_p == MAXNUM_P) {
    printf("Error: too many functions to set, the limit is %d", MAXNUM_P);
    return -1;
  }

  /* make sure that the index is mapped to only one ch handle */
  for(i=0; i<index_p; i++) {/* this ch function has been set */
    if(handlePairs[i].num == index) {
      handlePairs[i].handle_ch = handle_ch;
      handlePairs[i].usrMsg = usrMsg;
      break;
    }
  }
  if(i == index_p) { /* has never been set */
    handlePairs[index_p].num = index;
    handlePairs[index_p].handle_ch = handle_ch;
    handlePairs[index_p].usrMsg = usrMsg;
    index_p++;
  }

  retval = setHandle(index, chdl_funarg, (void *)&handlePairs[i]);
  Ch_VaEnd(interp, ap);
  return retval;
}

EXPORTCH void callFun_chdl(void *varg){
  ChVaList_t ap;
  int id;

  Ch_VaStart(interp, ap, varg);
  id = Ch_VaArg(interp, ap, int);         /* get 1st arg  */

  callFun(id);

  Ch_VaEnd(interp, ap);
  return;
}

static int chdl_funarg(void* pHandlePairs) {
  int retval;
 
  if (pHandlePairs == NULL) {
    printf("Error: The pHandlePairs pointer is NULL\n");
    retval =  -1;
  }
  else if(((struct HandlePairs *)pHandlePairs)->handle_ch) 
    Ch_CallFuncByAddr(interp, (void *)((struct HandlePairs *)pHandlePairs)->handle_ch, &retval, ((struct HandlePairs *)pHandlePairs)->usrMsg);

  return retval;
}
