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

/* The maximum number of ptfun4_setHandle()
   can be called */
#define MAXNUM   3

/* C functions to replace the Ch one */
static ChInterp_t interp;
static int (*ptfun4_chdl_funarg[MAXNUM])(float, int );

/* function pointers to save Ch function pointers */
static void *ptfun4_chdl_funptr[MAXNUM];

/* index of pointer pairs, from 0 to MAXNUM-1 */
static int index = 0;

EXPORTCH int ptfun4_setHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int id;
  funcHandle handle_ch, handle_c;
  int retval;

  Ch_VaStart(interp, ap, varg);
  id = Ch_VaArg(interp, ap, int);      /* get id of function handle */
  handle_ch = Ch_VaArg(interp, ap, funcHandle); /* get ch function pointer */

  if(handle_ch == NULL) {
    handle_c = NULL;
  }
  else {
    if(index == MAXNUM) {
      printf("Error: Only %d function pointers can be set\n", MAXNUM);
      return -1;
    }
    ptfun4_chdl_funptr[index] = (void *)handle_ch;
    handle_c = (funcHandle)ptfun4_chdl_funarg[index];
    index++;
  }

  retval = ptfun4_setHandle(id, handle_c);

  Ch_VaEnd(interp, ap);
  return retval;
}

EXPORTCH funcHandle ptfun4_getHandle_chdl(void *varg){
  int i;
  ChVaList_t ap;
  int id;
  funcHandle retval_c = NULL, retval_ch = NULL;

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

  retval_c = ptfun4_getHandle(id);

  /* replace C pointer with corresponding Ch function pointer */
  if(retval_c == NULL)  {
    retval_ch = NULL;
  }
  else {
    for(i = 0; i < index; i++) {
      if(ptfun4_chdl_funarg[i] == retval_c) {
        retval_ch = (funcHandle)ptfun4_chdl_funptr[i];
      }
    }
  }

  Ch_VaEnd(interp, ap);
  return retval_ch;
}

/**** hundreds of functions can be here ****/

static int ptfun4_chdl_funarg0(float f, int j) {
  int retval;

  Ch_CallFuncByAddr(interp, ptfun4_chdl_funptr[0], &retval, f, j);
  return retval;
}

static int ptfun4_chdl_funarg1(float f, int j) {
  int retval;

  Ch_CallFuncByAddr(interp, ptfun4_chdl_funptr[1], &retval, f, j);
  return retval;
}

static int ptfun4_chdl_funarg2(float f, int j) {
  int retval;

  Ch_CallFuncByAddr(interp, ptfun4_chdl_funptr[2], &retval, f, j);
  return retval;
}

/****initialization routine called in ptfun4.h **********/
EXPORTCH int ptfun4_setgetHandles_init() {
  /* from 0 to MAXNUM -1 */

   ptfun4_chdl_funarg[0] = ptfun4_chdl_funarg0;
   ptfun4_chdl_funarg[1] = ptfun4_chdl_funarg1;
   ptfun4_chdl_funarg[2] = ptfun4_chdl_funarg2;

   return 0;
}
