/***********************************************************************/
/* Open Visualization Data Explorer                                    */
/* (C) Copyright IBM Corp. 1989,1999                                   */
/* ALL RIGHTS RESERVED                                                 */
/* This code licensed under the                                        */
/*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
/***********************************************************************/
#include <dx/dx.h> 

#include <dxconfig.h>



typedef struct
{
  int  delete;
  char *message;
  char *messageType;
  char *major;
  char *minor;
} PendingDXLMessage;

static Error ManagePanels(Object *, char *);
static void delete_PendingDXLMessage(Pointer);
static Error SendPendingDXLMessage(Private);
static Error SendPendingMessage(char *, char *);

Error m_ManageSequencer(Object *in)
{
  char *name;
  int open=0;
  
  if (in[0])
    {
      if (!DXExtractInteger(in[0], &open))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"open must be 0 or 1");
	  goto error;
	}
      if ((open != 0)&&(open != 1))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"open must be 0 or 1");
	  goto error;
	}
    }
  
  if (open) 
    DXUIMessage("LINK", "open sequencer");
  else
    DXUIMessage("LINK", "close sequencer");
  
  return OK;
 error:
  return ERROR;	
}

Error m_InteractionMode(Object *in)
{
  char *mode, *tmpmode;
  int i, count;
  
  if (!in[0])
    mode = "none";
  else
    {
      if (!DXExtractString(in[0],&tmpmode))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"mode must be a string");
	  goto error;
	}
      
      mode = DXAllocate(strlen(tmpmode)+1);
      if (!mode)
	goto error;
      
      count = 0;
      i = 0;
      while (i<100 && tmpmode[i] != '\0')
	{
	  if (isalpha(tmpmode[i]))
	    {
	      if (isupper(tmpmode[i]))
		mode[count] = tolower(tmpmode[i]);
	      else
		mode[count] = tmpmode[i];
	      count++;
	    }
          i++;
	}
      mode[count]='\0';
    }
  
  if (!strcmp(mode,"camera"))
    DXUIMessage("LINK", "interactionMode camera");
  else if (!strcmp(mode,"cursors"))
    DXUIMessage("LINK", "interactionMode cursors");
  else if (!strcmp(mode,"pick"))
    DXUIMessage("LINK", "interactionMode pick");
  else if (!strcmp(mode,"navigate"))
    DXUIMessage("LINK", "interactionMode navigate");
  else if (!strcmp(mode,"panzoom"))
    DXUIMessage("LINK", "interactionMode panzoom");
  else if (!strcmp(mode,"roam"))
    DXUIMessage("LINK", "interactionMode roam");
  else if (!strcmp(mode,"rotate"))
    DXUIMessage("LINK", "interactionMode rotate");
  else if (!strcmp(mode,"zoom"))
    DXUIMessage("LINK", "interactionMode zoom");
  else if (!strcmp(mode,"none"))
    DXUIMessage("LINK", "interactionMode none");
  else
    {
      DXSetError(ERROR_BAD_PARAMETER,"action must be one of \"camera\", \"cursors\", \"pick\", \"navigate\", \"panzoom\", \"roam\", \"rotate\", \"zoom\", or \"none\"");
      goto error;
    }
  return OK;
 error:
  return ERROR;
  
}


Error m_Execute(Object *in)
{
  char *action, *tmpaction;
  int i, count;
  char buf[20];
  
  if (!in[0])
    action = "end";
  else
    {
      if (!DXExtractString(in[0],&tmpaction))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"action must be a string");
	  goto error;
	}
      
      action = DXAllocate(strlen(tmpaction)+1);
      if (!action)
	goto error;
      
      count = 0;
      i = 0;
      while (i<100 && tmpaction[i] != '\0')
	{
	  if (isalpha(tmpaction[i]))
	    {
	      if (isupper(tmpaction[i]))
		action[count] = tolower(tmpaction[i]);
	      else
		action[count] = tmpaction[i];
	      count++;
	    }
          i++;
	}
      action[count]='\0';
    }
  
#if 0
  if (!strcmp(action,"once"))
    DXUIMessage("LINK", "execute once");
  else if (!strcmp(action,"onchange"))
    DXUIMessage("LINK", "execute onchange");
  else if (!strcmp(action,"end"))
    DXUIMessage("LINK", "execute end");
  else
    {
      DXSetError(ERROR_BAD_PARAMETER,"action must be one of \"once\", \"on change\" or \"end\"");
      goto error;
    }
#endif

  if (!strcmp(action,"once"))
    sprintf(buf, "execute once");
  else if (!strcmp(action,"onchange"))
    sprintf(buf, "execute onchange");
  else if (!strcmp(action,"end"))
    sprintf(buf, "execute end");
  else
    {
      DXSetError(ERROR_BAD_PARAMETER,"action must be one of \"once\", \"on change\" or \"end\"");
      goto error;
    }

  SendPendingMessage(buf, "default");

  return OK;
 error:
  return ERROR;
  
}


Error m_ManageColormapEditor(Object *in)
{
  
  if (!ManagePanels(in, "colormap"))
    goto error;
  
  return OK;
  
 error:
  return ERROR;
}

Error ManagePanels(Object *in, char *paneltype)
{
  char *name = "", *openname, *how, *buf = NULL;
  int i, j, open, nummaps, numflags, num_in_open_list;
  int *open_list, rank, shape[10];
  Array open_list_array;
  Type type=TYPE_STRING;
  char messageid[20];
  
  if (!strcmp(paneltype,"colormap")&& 
      !strcmp(paneltype,"image")&&
      !strcmp(paneltype,"controlpanel"))
    {
      DXSetError(ERROR_INTERNAL,"unrecognized paneltype %s", paneltype);
      goto error;
    } 
  
  sprintf(messageid,"default");
  /* can be a single string or a list of strings */  
  if (in[0])
    {
      if (!DXExtractNthString(in[0], 0, &name))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"name must be a string");
	  goto error;
	}
      /* how many strings are there */
      if (!_dxfHowManyStrings(in[0], &nummaps)) 
        goto error;
    }
  
  /* it can be an integer, integer list, or string list */  
  if (in[1])
    {
      if (DXGetObjectClass(in[1])==CLASS_ARRAY)
	{
	  if (!DXGetArrayInfo(in[1], &numflags, &type, NULL, &rank, shape))
	    goto error;
	  if (type == TYPE_INT)
	    {
	      if (!(rank == 0)||((rank == 1)&&(shape[0]==1)))
		{
		  DXSetError(ERROR_INVALID_DATA,
			     "open must be an integer list or string list");
		  goto error;
		}
	      open_list = (int *)DXGetArrayData(in[1]);
	    }
	  else if (type!=TYPE_STRING)
	    {
	      DXSetError(ERROR_INVALID_DATA,
			 "open must be an integer list or string list");
	      goto error;
	    }
          if (numflags==1)
	    DXExtractInteger(in[1], &open);
	}
      else if (!(DXGetObjectClass(in[1])==CLASS_STRING))
	{
	  DXSetError(ERROR_INVALID_DATA,
		     "open must be an integer list or string list");
	  goto error;
        }
    }
  else
    {
      /* default */
      open=0;
      numflags=1;
      type = TYPE_INT;
    }
  
  
  if (!strcmp(paneltype,"colormap")|| !strcmp(paneltype,"image"))
    {
      if (in[2])
	{
	  if (!DXExtractString(in[2], &how))
	    {
	      DXSetError(ERROR_BAD_PARAMETER,"how must be either \"title\" or \"label\"");
	      goto error;
	    }
	  if (!strcmp(how,"title")&&(!strcmp(how,"label")))
	    {
	      DXSetError(ERROR_BAD_PARAMETER,"how must be either \"title\" or \"label\"");
	      goto error;
	    }
	}
      else 
	how="title";
    }
  
  buf = DXAllocate(strlen(name)+50);
  if (!buf)
    goto error; 
  
  
  if (type == TYPE_INT) 
    {
      if ((numflags != 1)&&(numflags != nummaps))
	{
	  DXSetError(ERROR_INVALID_DATA,
		     "open must be one integer or must be a list which matches name");
	  goto error; 
	}
      if (numflags == 1) 
	{
	  if (open)
	    {
	      if (in[0])
		{
                  for (j=0; j<nummaps; j++)
		    {
		      DXExtractNthString(in[0],j,&name);
                      if (!strcmp(paneltype,"colormap"))
		        sprintf(buf, "open colormapEditor %s=%s", how, name);
                      else if (!strcmp(paneltype,"image"))
		        sprintf(buf, "open image %s=%s", how, name);
                      else 
		        sprintf(buf, "open controlpanel %s", name);
                      sprintf(messageid,"%i", j);
                      if (!SendPendingMessage(buf, &messageid))
			goto error;
		    }
		}
	      else
                {
                  if (!strcmp(paneltype,"colormap"))
		    sprintf(buf, "open colormapEditor");
                  else if (!strcmp(paneltype,"image"))
		    sprintf(buf, "open image");
                  else
		    sprintf(buf, "open controlpanel");
		  if (!SendPendingMessage(buf, messageid))
		    goto error;
                }
	    }
	  else
	    {
	      if (in[0])
		{
                  for (j=0; j<nummaps; j++)
		    {
		      DXExtractNthString(in[0],j,&name);
                      if (!strcmp(paneltype,"colormap"))
			sprintf(buf, "close colormapEditor %s=%s", how,name);
                      else if (!strcmp(paneltype,"image"))
			sprintf(buf, "close image %s=%s", how,name);
                      else 
			sprintf(buf, "close controlpanel %s", name);
                      sprintf(messageid,"%d",j);
                      if (!SendPendingMessage(buf, messageid))
			goto error;
		    }
		}
	      else
		{
                  if (!strcmp(paneltype,"colormap"))
		    sprintf(buf, "close colormapEditor");
                  else if (!strcmp(paneltype,"image"))
		    sprintf(buf, "close image");
                  else  
		    sprintf(buf, "close controlpanel");
		  if (!SendPendingMessage(buf, messageid))
		    goto error;
		}
	    }
	}
      else
	{
	  for (j=0; j<nummaps; j++)
            {
	      open = open_list[j];
	      DXExtractNthString(in[0],j,&name);
	      if (open)
                {
		  if (!strcmp(paneltype,"colormap"))
		    sprintf(buf, "open colormapEditor %s=%s", how,name);
		  else if (!strcmp(paneltype,"image"))
		    sprintf(buf, "open image %s=%s", how,name);
		  else
		    sprintf(buf, "open controlpanel %s", name);
                }
	      else
                {
		  if (!strcmp(paneltype,"colormap"))
		    sprintf(buf, "close colormapEditor %s=%s", how,name);
		  else if (!strcmp(paneltype,"image"))
		    sprintf(buf, "close image %s=%s", how,name);
		  else
		    sprintf(buf, "close controlpanel %s", name);
                }
              sprintf(messageid,"%d",j);
	      if (!SendPendingMessage(buf, messageid))
		goto error;
            }
	}
    }
  else
    /* else "open" is a string list, of the ones which should be
       open. All others should be closed */
    {
      if (!_dxfHowManyStrings(in[1], &num_in_open_list)) 
	goto error;
      for (i=0; i<nummaps; i++) 
	{
          DXExtractNthString(in[0],i,&name);
          open=0;
          for (j=0; j<num_in_open_list; j++)
            {
	      DXExtractNthString(in[1],j,&openname);
	      if (!strcmp(name,openname)) 
		{
                  open=1;
                  break;
		}
            }
	  if (open)
	    {
	      if (!strcmp(paneltype,"colormap"))
		sprintf(buf, "open colormapEditor %s=%s", how,name);
	      else if (!strcmp(paneltype,"image"))
		sprintf(buf, "open image %s=%s", how,name);
	      else
		sprintf(buf, "open controlpanel %s", name);
	    }
	  else
	    {
	      if (!strcmp(paneltype,"colormap"))
		sprintf(buf, "close colormapEditor %s=%s", how,name);
	      else if (!strcmp(paneltype,"image"))
		sprintf(buf, "close image %s=%s", how,name);
	      else
		sprintf(buf, "close controlpanel %s", name);
	    }
	  sprintf(messageid,"%d",i);
	  if (!SendPendingMessage(buf, messageid))
	    goto error;
	}
    }
  
  
  if (buf) DXFree((Pointer)buf);
  return OK;

 error:
  if (buf) DXFree((Pointer)buf);
  return ERROR;	
}


extern int _dxf_mapSupervisedWindow(char *, int);

Error m_ManageImageWindow(Object *in)
{
  char *where;
  int map;

  if (! DXExtractString(in[0], &where) ||
      ! DXExtractInteger(in[1], &map) ||
      ! _dxf_mapSupervisedWindow(where, map))
    if (!ManagePanels(in, "image"))
      goto error;

  return OK;

error:
  return ERROR;
}


Error m_OpenVisualProgram(Object *in)
{
  /* this one sets pending to 1 */
  char *name, *buf;
  int flush=1;
  char messageid[20];
  
  sprintf(messageid,"default");
  
  
  if (in[0])
    {
      if (!DXExtractString(in[0], &name))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"name must be a string");
	  goto error;
	}
    }
  else
    {
      DXSetError(ERROR_MISSING_DATA,"name must be specified");
      goto error;
    }

  if (in[1])
    {
      if (!DXExtractInteger(in[1], &flush))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"flush must be 0 or 1");
	  goto error;
	}
      if ((flush != 0)&&(flush != 1))
	{
	  DXSetError(ERROR_BAD_PARAMETER,"flush must be 0 or 1");
	  goto error;
	}
    }

  buf = DXAllocate((strlen(name)+50));
  if (!buf)
     goto error;

  if (flush)
    sprintf(buf, "open network %s", name);
  else
    sprintf(buf, "open networkNoReset %s", name);

  if (!SendPendingMessage(buf, messageid))
    goto error;
  
  return OK;
 error:
  return ERROR;	
}

static Error
  SendPendingDXLMessage(Private P)
{
  PendingDXLMessage *p = (PendingDXLMessage *)DXGetPrivateData(P);
  
  DXUIMessage(p->messageType, p->message);
  
  if (p->delete)
    if (! DXSetPendingCmd(p->major, p->minor, NULL, NULL))
      {
	DXSetError(ERROR_INTERNAL, "error return from DXSetPendingCmd");
	return ERROR;
      }
  
  return OK;
}


static void delete_PendingDXLMessage(Pointer d)
{
  PendingDXLMessage *p = (PendingDXLMessage *)d;
  DXFree(p->message);
  DXFree(p->messageType);
  DXFree(p->major);
  DXFree(p->minor);
  DXFree(p);
}



Error m_ManageControlPanel(Object *in)
{

  if (!ManagePanels(in, "controlpanel"))
     goto error;

  return OK;

error:
  return ERROR;
}


static Error GetFlag(Object obj, int *flag)
{

  if (!DXExtractInteger(obj,flag))
    {
      DXSetError(ERROR_BAD_PARAMETER,"flag must be 0 or 1");
      goto error;
    }
  if ((*flag != 0) && (*flag != 1))
    {
      DXSetError(ERROR_BAD_PARAMETER,"flag must be 0 or 1");
      goto error;
    }
  return OK;
 error:
  return ERROR;
}
      
      
static Error SendPendingMessage(char *buf, char *messageid)
{
  char *major = NULL;
  PendingDXLMessage *plr = NULL;
  Private p = NULL;

  plr = (PendingDXLMessage *)DXAllocateZero(sizeof(PendingDXLMessage));
  if (!plr)
     goto error;
      
  plr->message = (char *)DXAllocate(strlen(buf)+1);
  if (!plr->message)
     goto error;
      
  plr->messageType = (char *)DXAllocate(5);
  if (!plr->messageType)
     goto error;

  major = DXGetModuleId();
  if (!major)
     goto error;

  plr->major = (char *)DXAllocate(strlen(major)+1);
  if (!plr->major)
     goto error;
      
  plr->minor = (char *)DXAllocate(strlen(messageid)+1);
  if (!plr->minor)
     goto error;
      

  p = DXNewPrivate((Pointer)plr, delete_PendingDXLMessage);
  if (!p)
     goto error;
      
  strncpy(plr->message, buf, strlen(buf)+1);
  strncpy(plr->messageType, "LINK", 5);
  strncpy(plr->major, major, strlen(major)+1);
  strncpy(plr->minor, messageid, strlen(messageid)+1);
      
  DXFreeModuleId(major);
  major = NULL;
      
  plr->delete = 1;
      
  if (!DXSetPendingCmd(plr->major, messageid, SendPendingDXLMessage, p))
     goto error;
  return OK;
  
error:    
  if (p)
    DXDelete((Object)p);
  else if (plr)
    {
      DXFree(plr->major);
      DXFree(plr->minor);
      DXFree(plr->message);
      DXFree(plr->messageType);
      DXFree(plr);
    }
  
  if (major)
    DXFreeModuleId(major);
  return ERROR;
  
}
