// test program for detach mechanasim

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

static int insertData (cdevData& out, int type, int count)
{
  int dataStatus = 0;
  if (count == 1){
    switch (type){
    case 0:
      {
	char temp[40];
	printf ("Enter char string\n");
	scanf ("%s",temp);
	dataStatus = out.insert ("value", temp);
      }
      break;
    case 1:
    case 5:
      {
	int val;
	printf ("Enter Integer Value \n");
	scanf ("%d", &val);
	dataStatus = out.insert ("value", val);
      }
      break;
    case 2:
      {
	float  fval;
	printf ("Enter double value \n");
	scanf ("%f", &fval);
	dataStatus = out.insert ("value", fval);
      }
    case 6:
      {
	double val;
	float  fval;
	printf ("Enter double value \n");
	scanf ("%f", &fval);
	val = (double)fval;
	dataStatus = out.insert ("value", val);
      }
      break;
    default:
      printf ("unsupported data type %d\n", type);
      break;
    }
  }
  else {
    switch (type){
    case 0:
      {
	static counter = 0;
	char **temp = new char* [count];
	for (int i = 0; i < count; i++){
	  temp[i] = new char[40];
	  sprintf (temp[i], "Hello again there %d", i * counter);
	}
	dataStatus = out.insert ("value",temp, count);
	for (i = 0; i < count; i++)
	  delete []temp[i];
	delete []temp;
	counter++;
	if (counter > 10)
	  counter = 0;
      }
      break;
    case 1:
    case 5:
      {
	static counter = 1;
	int *temp = new int[count];
	for (int i = 0; i < count; i++)
	  temp[i] = i*counter;
	dataStatus = out.insert ("value",temp, count);
	delete []temp;
	counter++;
	if (counter > 3)
	  counter = 1;
      }
      break;
    case 6:
      {
	static counter = 1;
	double *temp = new double[count];
	for (int i = 0; i < count; i++)
	  temp[i] = i*(counter);
	dataStatus = out.insert ("value",temp, count);
	delete []temp;
	counter++;
	if (counter > 3)
	  counter = 1;
      }      
      break;
    default:
      break;
    }
  }
  return dataStatus;
}

static void printValue (cdevData& result)
{
  size_t len1, dim, type;
  int tag;
  result.tagC2I ("value", &tag);
  int st = result.getDim (tag, &dim);
  if (dim != 0)
    {
    // ***********************************************************************
    // * cdevBounds support added for support of arbitrary dimensional data
    // ***********************************************************************
    cdevBounds bounds;
    st = result.getBounds (tag, &bounds, 1);
    len1 = bounds.length;
    }
  else
    len1 = 1;
  printf ("Length is %d\n", len1);
  type = result.getType (tag);
  printf ("data type is %d\n",type);
  float lval, hval;
  st = result.get ("displayHigh", &hval);
  if (st == CDEV_SUCCESS)
    printf ("Display High limit is %f\n", hval);
  st = result.get ("displayLow", &lval);
  if (st == CDEV_SUCCESS)
    printf ("Display Low Limit is %f\n", lval);
  switch (type){
  case CDEV_INT32:
    if (len1 == 1){
      int retVal;
      result.get (tag, &retVal);
      printf ("result is %d\n",retVal);
    }
    else{
      int *retVal = new int[len1];
      result.get (tag, retVal);
      printf ("result is \n");
      for (int i = 0; i < len1; i++)
	printf ("%d\n", retVal[i]);
      printf ("__________________\n");
      delete []retVal;
    }
    break;
  case CDEV_FLOAT:
    if (len1 == 1) {
      float dval;
      result.get (tag, &dval);
      printf ("result is %f\n", dval);
    }
    else {
      float *dval = new float[len1];
      result.get (tag, dval);
      for (int i = 0; i < len1; i++)
	printf ("%f\n", dval[i]);
      printf ("__________________\n");
      delete []dval;	  
    }
    break;
  case CDEV_DOUBLE:
    if (len1 == 1) {
      double dval;
      result.get (tag, &dval);
      printf ("result is %f\n", dval);
    }
    else {
      double *dval = new double[len1];
      result.get (tag, dval);
      for (int i = 0; i < len1; i++)
	printf ("%f\n", dval[i]);
      printf ("__________________\n");
      delete []dval;	  
    }
    break;
  case CDEV_STRING:
    if (len1 == 1){
      char temp[40];
      result.get (tag,temp, sizeof (temp));
      printf ("result is %s\n", temp);
    }
    else{
      char **temp;
      temp = new char* [len1];
      
      result.get (tag, temp);
      
      printf ("Strings are \n");
      for (int i = 0; i < len1; i++){
	printf ("%s\n",temp[i]);
	delete []temp[i];
      }
      delete []temp;
    }
    break;
  default:
    printf ("Something is wrong\n");
    break;
  }
}

static void myCallback (int status, void *userarg,
			cdevRequestObject &obj, cdevData& result)
{
  printf ("user get callback called++++++++\n");
  printValue (result);
}

static void mySetCallback (int status, void *userarg,
			cdevRequestObject &obj, cdevData& result)
{
  printf ("user set callback called======================\n");
}

static int done = 0;

main (int argc, char **argv)
{
  cdevSystem& system = cdevSystem::defaultSystem ();
  cdevCallback getCallback(myCallback, 0);
  cdevCallback setCallback(mySetCallback, 0);

  char command[40];
  char deviceName[40], messageName[64], attname[30];
  cdevData result;
  cdevData cxt;
  int st = cxt.insert ("value", 100);
  st = cxt.insert ("displayHigh", 1);
  cxt.insert ("displayLow", 1);

  while (!done){
    fprintf (stdout, "cdevTest Command>");
    scanf ("%s", command);
    if (::strcmp (command, "get") == 0){
      printf ("cdevTest devicename attribute> \n");
      scanf ("%s %s",deviceName, attname);
      ::strcpy (messageName, command);
      ::strcat (messageName, " ");
      ::strcat (messageName, attname);
      cdevDevice *dev = system.getDevice (deviceName);
      cdevRequestObject *req = dev->getRequestObject (messageName);
//      cdevRequestObject& req = 
//	cdevRequestObject::attachRef (deviceName, messageName);
      req->setContext (cxt);
//      cdevGroup grp;
//      grp.start ();
//      int st = req->sendCallback (0, getCallback);
//      int st = req->sendNoBlock (0, result);
      result.remove ();
      int st = req->send (0, result);
      if (st == CDEV_SUCCESS){
//	grp.end ();
//	st = grp.pend ();
//	if (grp.allFinished ())
//	  printf ("All transaction finished\n");
	if (st == CDEV_SUCCESS)
	  result.asciiDump();
	else{
	  printf("send failed-----\n");
	}
      }
      else 
	printf ("Send failed immedaitely\n");
      // detach device
      cdevRequestObject::detach (req);
    }
    else if (::strcmp (command, "set") == 0){
      printf ("cdevTest devicename attribute> \n");
      scanf ("%s %s",deviceName, attname);
      ::strcpy (messageName, command);
      ::strcat (messageName, " ");
      ::strcat (messageName, attname);
      cdevRequestObject& req = 
	cdevRequestObject::attachRef (deviceName, messageName);
      int type, count;
      printf ("Supported type are: \n");
      printf ("0: string. 1: short. 2: float, 5: long, 6: double\n");
      printf ("Enter type and count for this channel\n");
      scanf ("%d %d",&type, &count);
      cdevData out;
      int dataStatus = insertData (out, type, count);
      if (dataStatus == CDEV_SUCCESS){
	cdevGroup grp;
	grp.start ();
//	int st = req.sendCallback (out, setCallback);
	int st = req.sendNoBlock (out, 0);
//	int st = req.send (out, 0);
	grp.end ();
	st = grp.pend ();
	if (grp.allFinished ())
//	if (st == CDEV_SUCCESS)
	  printf ("Set success\n");
	else
	  printf ("Set failed\n");
	cdevRequestObject::detach (req);
      }
      else 
	printf ("Data Insersion Error\n");
    }
    else if (::strcmp (command, "monitorOn") == 0){
      printf ("cdevTest devicename attribute> \n");
      scanf ("%s %s",deviceName, attname);
      ::strcpy (messageName, command);
      ::strcat (messageName, " ");
      ::strcat (messageName, attname);
      cdevRequestObject& req = 
	cdevRequestObject::attachRef (deviceName, messageName);
      cdevGroup grp;
      grp.start ();
      int st = req.sendCallback (0, getCallback);
      grp.end ();
      st = grp.pend (10.0);
      if (grp.allFinished ())
	printf ("Monitor On success\n");
      else
	printf ("MonitorOn failed\n");
      system.pend (50.0);
    }
    else if (::strcmp (command, "quit") == 0)
      done = 1;
    else {
      printf ("Legal commands are: get, quit\n");
    }
  }

}    
