// test program for channel access

#include <cdevSystem.h>
#include <cdevRequestObject.h>
#include <cdevDevice.h>
#include <cdevGroup.h>
#include <cdevErrCode.h>
#include <unistd.h>


static void
mycallback (int status, void *userarg, 
	    cdevRequestObject &obj, cdevData& result)
{
  printf("user callback called+++++++++++++++++++++++++++++++++++++++\n");
  printf("call status is %d\n",status);
  float fval;
  result.get ("value",&fval);
  printf("return value from callback is %f\n",fval);
}

static void checkDevice()
{
  cdevData cxt;

  cxt.insert("time", 1);
  cxt.insert("status", 1);
  cxt.insert("displayHigh", 1);
  cxt.insert("displayLow", 1);

  cdevDevice& device1 = cdevDevice::attachRef ("cdev_ai0");
  cdevDevice& device2 = cdevDevice::attachRef ("cdev_aout0");
  cdevDevice& device3 = cdevDevice::attachRef ("cdev_strin0");
  cdevData out;
  cdevData result;

  device1.setContext (cxt);
  int st = device1.send ("get", 0, result);
  if (st != CDEV_SUCCESS)
    printf("Cannot send out, database not found \n");
  double dval, dispHi, dispLo;
  result.get ("value", &dval);
  result.get ("displayHigh",&dispHi);
  result.get ("displayLow", &dispLo);
  printf("get cdev_ai0 value %f displayHigh %f displayLow %f \n",dval, 
	 dispHi, dispLo);
  st = device2.send ("get", 0, result);
  result.get ("value", &dval);
  printf("get cdev_aout0 value %f \n",dval);

  st = device3.send ("get", 0, result);
  char temp[40];
  result.get ("value", temp, sizeof (temp));
  printf ("value from string field is < %s > \n", temp);

  st = device2.send ("get SCAN", 0, result);

  result.get ("value", temp, sizeof (temp));
  printf("result get from scan field is %s \n",temp);
  
  result.cleanup();
  result.insert ("value", "10 second");
  st = device2.send ("set SCAN", result, 0);

  cdevDevice::detach (device2);
  cdevDevice& device5 = cdevDevice::attachRef ("cdev_aout0");
  device5.send ("get SCAN", 0, result);
  result.get ("value", temp, sizeof (temp));
  printf("result get from scan field is %s \n",temp);  
}

main (int argc, char **argv)
{
  cdevSystem& system = cdevSystem::defaultSystem();
  cdevData cxt;

  checkDevice();

  printf("finished subroutines>>>>>>>>>>>>>>>>>>>\n");
  cxt.insert("time", 1);
  cxt.insert("status", 1);
  cxt.insert("displayHigh", 1);
  cxt.insert("displayLow", 1);

  cdevDevice& device1 = cdevDevice::attachRef ("cdev_ai0");
  cdevDevice& device2 = cdevDevice::attachRef ("cdev_aout0");
  cdevDevice& device3 = cdevDevice::attachRef ("cdev_strin0");
  cdevDevice* device10 = system.getDevice ("cdev_aout1");

  cdevData out;
  cdevData result;

  device1.setContext (cxt);
  int st = device1.send ("get", 0, result);
  if (st == CDEV_SUCCESS)
    printf("device1 sendout success\n");
  st = device2.send ("get", 0, result);
  if (st == CDEV_SUCCESS)
    printf("device2 sendout success\n");
  st = device3.send ("get", 0, result);
  if (st == CDEV_SUCCESS)
    printf("device3 sendout success\n");
  st = device10->send ("get", 0, result);
  printf ("st fro device10 is %d\n",st);
  if (st == CDEV_SUCCESS)
    printf("device10 sendout success\n");  

  out.cleanup();
  out.insert ("value",8723.22);
  st = device2.send ("set", out, 0);
  if (st == CDEV_SUCCESS)
    printf("send set sync success+++++++\n");
  else
    printf("send set sync failed\n");

  device1.sendNoBlock ("get", 0, result);
  device2.sendNoBlock ("get", 0, result);

  cdevCallback callback(mycallback, 0);

  device2.sendCallback ("get", out, callback);

  // youe have no way to find out whether there are something pending
  // you can either do this or do system.pend ()

//  int j = 0;
//  while (j < 1000){
//    system.poll ();
//    j++;
//  }
  system.pend (2.0);

  printf("###############################################\n");
  
  cdevGroup g1(10), g2(5);
  g1.start();
  int i;
  for (i = 0; i < 1; i++)
    device1.sendNoBlock ("get",out, result);
  g2.start();
  device1.sendNoBlock ("get",out, result);
  device2.sendNoBlock ("get",out, result);
  device3.sendNoBlock ("get",0, result);
  out.cleanup();
  out.insert ("value", (float)3456.78);
  device2.sendNoBlock ("set", out, 0);
  device2.sendNoBlock ("get HOPR", 0, result);
//  device2.sendNoBlock ("get TIME", 0, result);
  g1.end();
  device1.sendNoBlock ("get",out, result);
  for (i = 0; i < 1; i++)
    device2.sendCallback ("get", out, callback);
  g2.end();
  g1.pend(10.0);
  if (g1.allFinished()){
    printf("g1 transaction all finished\n");
  }
  else{
    printf("g1 has unfinished transactions\n");
  }
  g2.pend (10.0);
  if (g2.allFinished()){
    printf("g2 transaction all finished\n");
  }
  else{
    printf("g2 has unfinished transactions\n");
  }
  int status[100];
  int numx = 100;
  g2.status (status, numx);
  for (i = 0; i < numx; i++){
    printf("status[%d] is %d\n",i, status[i]);
  }

  cdevDevice::detach (device3);

  // test monitor on
  g1.start ();
  device1.sendCallback ("monitorOn", 0, callback);
  device2.sendCallback ("monitorOn", 0, callback);
//  g1.end();
  g1.pend (10.0);
  if (g1.allFinished()){
    printf("g1 again finished all transaction\n");
  }

  system.pend (10.0);
  
  return 0;
}

