/*******************************************************************************
Moritz Haag      8.01.2003
Functions to create GnuPlot-Work-Files 
and to send Data to GnuPlot or into DataFiles
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include "check_malloc.h"
#include "gnuplot.h"

/*****************************************************************************
| Add new Plot Command to GnuPlot Datastructure 
| Group ....
*****************************************************************************/
void AddPlot(GnuPlot *aktplot, int Group, char *newCmd)
{
  PlotCmd *tmp=NULL;
  aktplot->plotcnt++;
  if(aktplot->plotcnt<=1)
  {
     tmp=(PlotCmd *)check_malloc(aktplot->plotcnt*sizeof(PlotCmd));
  }
  else
  {
    tmp=(PlotCmd *)check_realloc(aktplot->plots,aktplot->plotcnt*sizeof(PlotCmd));
  }
  strcpy(tmp[(aktplot->plotcnt)-1].Str,newCmd);
  tmp[(aktplot->plotcnt)-1].PlotGroup = Group;
  aktplot->plots=tmp;
}

/*****************************************************************************
| create Dat-Datei overwrite if it exists
| The DataArrays must be stored in a GnuData  structure first.
| Be sure that the GnuData structure contains the correct values for x-Rows and
| y columns
| Later : get dimensions automatically
*****************************************************************************/
void CreatePlotData(GnuPlot *aktplot, char *fname, GnuData *data, int PlotGroup)
{
  int i,j;
  char *tmp=NULL;
  FILE *gd=NULL;
  gd=fopen(fname,"r");
  if (gd==NULL || 1) /*existierende Datei ueberschreiben AUSBLICk:Frage*/ 
  {
    gd=fopen(fname,"w");
    fprintf(gd, "# Dies ist eine GnuPlot Datendatei erzeugt von GnuPlotC\n");
    fprintf(gd, "# Diese Datei gehoert zur %s Datei.\n", aktplot->name);
    fprintf(gd, "# in der auch die Formatierung geregelt wird.\n");
    fprintf(gd, "# %s  ",data->xname);
    for(j=0;j<data->ycolumns;j++)
      {
	 fprintf(gd, "  %s  ",data->ydata[j].name);
      }
    fprintf(gd, "\n");

    fprintf(gd, "# Daten\n");
    for(i=0;i<data->xcnt;i++)
    {
      fprintf(gd, "%f ",data->xdata[i]);
      for(j=0;j<data->ycolumns;j++)
      {
	 fprintf(gd, "%f ",data->ydata[j].data[i]);
      }
      fprintf(gd, "\n");
    }
    fprintf(gd, "# Ende der Daten\n");
    fclose(gd);
    tmp=(char *)check_malloc(sizeof(fname)+2*sizeof(char));
    sprintf(tmp,"%s%s%s","\"",fname,"\"");
    strcpy(tmp,"\"");
    strcat(tmp,fname);
    strcat(tmp,"\"");
    AddPlot(aktplot,PlotGroup,tmp);
    check_free(tmp);/**/
  }
  else
  {
    printf("Datei existiert bereits.");
  }
}

/*****************************************************************************
| Creater Gnu-Work-File to save Chartproperties 
| if Overwrite ist not 0 the existing file will be overwritten else 
| the routine will be cancled 
| After each Plotgroup Enter has to be pressed to continue
*****************************************************************************/
void CreateGnuFile(GnuPlot *aktplot, int overwrite)
{
  int group[MAX_GROUPS+1];
  int i,j,k;
  FILE *gd;
  gd=fopen(aktplot->name,"r");
  if ((gd==NULL) || overwrite) 
  {
    gd=fopen(aktplot->name,"w");
    /*----------------------------------------------------------------------------
    | pruefe ob (aktplot->name).gnu vorhanden
    ----------------------------------------------------------------------------*/
    fprintf(gd, "# GnuPlot Diagrammdatei\n");
    fprintf(gd, "# erzeugt von GnuPlotC by Moritz Haag\n");
    fprintf(gd, "# Formatdefinitionen\n");
    fprintf(gd, "set xrange[%4f:%4f]\n",aktplot->xmin, aktplot->xmax);
    fprintf(gd, "set yrange[%4f:%4f]\n",aktplot->ymin, aktplot->ymax);
    fprintf(gd, "set xlabel \"%s\"\n",aktplot->xlable);
    fprintf(gd, "set ylabel \"%s\"\n",aktplot->ylable);
    fprintf(gd, "set zlabel \"%s\"\n",aktplot->zlable);
    fprintf(gd, "set title \"%s\"\n",aktplot->title);
    fprintf(gd, "# Plotdaten\n");
    for(j=0;j<=MAX_GROUPS;j++)
      group[j]=0;

    /**Schreibe in Matrix Anzahl der plots in Gruppe**/
    aktplot->grpcnt = 0;
    for(i=0;i<aktplot->plotcnt;i++)
    {
      group[aktplot->plots[i].PlotGroup]++;
      if(group[aktplot->plots[i].PlotGroup]==1)
        aktplot->grpcnt++;
    }
    for(j=0;j<=MAX_GROUPS;j++)
    {
      if(group[j])
      {
        fprintf(gd, "plot ");
        k=0;
        for(i=0;i<aktplot->plotcnt;i++)
        {
          if(aktplot->plots[i].PlotGroup==j)
          {
            fprintf(gd, "%s",aktplot->plots[i].Str);
            k++;
            if(k<group[j])
              fprintf(gd, ",");
          }  
        }
        fprintf(gd, "\n");
        fprintf(gd, "pause -1\n");
      }/** if group*/
    }/**for(j=0;j<=MAX_GROUPS;j++)**/
    fprintf(gd, "# Ende der Datei\n");
    fclose(gd);
  }
}

/*****************************************************************************
| Show Gnu-Plot from Wok-File, update Workfile first
*****************************************************************************/
void ShowPlot(GnuPlot *aktplot, GNU_PROCESS *gp)
{
  int i=1;
  GNU_PROCESS *igp;
  char *temp;
  CreateGnuFile(aktplot,1); /*ACHTUNG: overwrite Wert fest gestezt!*/
  if (gp == NULL)
    igp = OpenGnuPlot();
  else
    igp = gp;
  temp = (char *)check_malloc(MAX_CMD_LEN*sizeof(char));
  strcpy(temp,"load '");
  strcat(temp,aktplot->name);
  strcat(temp,"'\n");
  SendGnuCmd(igp, temp);
/* um Pausen einzuhalten */
  for (i=1;i<aktplot->grpcnt;i++) SendGnuCmd(igp, "\n");
  check_free(temp);
  if (gp == NULL) CloseGnuPlot(igp);
}

/*****************************************************************************
| Open new GnuPlot Process (dont't forget to close later)
*****************************************************************************/
GNU_PROCESS *OpenGnuPlot()
{
   GNU_PROCESS *igp = NULL; /*intern GnuPlotProcessId */
   igp = popen(GNUPLOT_PATH, "w");
   if(igp == NULL)
   {
     fprintf(stderr, "GNUPlot nicht gefunden an %s!", GNUPLOT_PATH);
   }
   return igp;
}

/*****************************************************************************
| Send command dircet to GNUPlot-Process
| IGP mus be an open GnuProcess
| Command must end with an \n
*****************************************************************************/
void SendGnuCmd(GNU_PROCESS *igp, char *aktCmd)
{
   fprintf(igp, aktCmd);
   fflush(igp); /* WICHTIG! */
   getchar();
}


/*****************************************************************************
| Create Plot-Command from given function
| offers the possibility to modify plotcommd simple for 3D or other plotter
*****************************************************************************/
char *CreatePlotCmd(char *aktCmd)
{
   char *fullcmd;
   fullcmd = (char *)check_malloc((MAX_CMD_LEN +8)*sizeof(char));
   strcpy(fullcmd, "plot ");
   strcat(fullcmd, aktCmd);
   strcat(fullcmd, "\n");
   return fullcmd;
}

/*****************************************************************************
| Set Plotarray data to initial values.
| plotcnt MUST be set to zero.
*****************************************************************************/
void init_plot(GnuPlot *DefPlot)
{
   DefPlot->xmin = -5.;
   DefPlot->xmax = 5.;
   DefPlot->ymin = -5.;
   DefPlot->ymax = 5.;
   DefPlot->plotcnt = 0;
   strcpy(DefPlot->name, "Plotfile1.gnu");
}

#ifdef DEBUG
/*****************************************************************************
| Test main to demonstrate functions without other program
| requires compiler option -DDEBUG
*****************************************************************************/
int main()
{
  GnuPlot MyPlot;
  GNU_PROCESS *gp;
  char *temp;
  double My_x[] = {0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1};
  double My_y1[] = {0.01,0.12,0.23,0.34,0.45,0.56,0.67,0.78,0.89,0.91};
  double My_y2[] = {0.001,0.012,0.013,0.024,0.025,0.036,0.037,0.048,0.059,0.01};
  GnuData MyData; 
  /*--------------------------------------------------
  test for direkte communication
  --------------------------------------------------*/
# ifdef DIRECT
  {
    gp = OpenGnuPlot();
    SendGnuCmd(gp, "set title \" Moritz \"\n");
    temp = CreatePlotCmd("sin(x)");
    SendGnuCmd(gp, temp);
    check_free(temp);
    CloseGnuPlot(gp);
  }
#endif
  /*--------------------------------------------------
   test fuer indirect communication
  --------------------------------------------------*/
  {
    init_plot(&MyPlot);
    MyPlot.ymin = -1.5;
    MyPlot.ymax = 1.5;
    strcpy(MyPlot.name, "test.gnu");
    strcpy(MyPlot.title, "Moritz");
    strcpy(MyPlot.xlable, "Zeit");
    strcpy(MyPlot.ylable, "Werte");
    strcpy(MyPlot.zlable, "");
    AddPlot(&MyPlot,1,"cos(x)");
    AddPlot(&MyPlot,1,"sin(x)");
    AddPlot(&MyPlot,2,"x**2");
    AddPlot(&MyPlot,3,"x**3");
    AddPlot(&MyPlot,4,"x**4");
    AddPlot(&MyPlot,4,"x**5");
    MyData.xcnt=10;
    MyData.ycolumns=2;
    strcpy(MyData.xname,"Zeit");
    MyData.xdata=My_x;
    strcpy(MyData.ydata[0].name,"Wert");
    MyData.ydata[0].data=My_y1;
    strcpy(MyData.ydata[1].name,"Fehler");
    MyData.ydata[1].data=My_y2;
    CreatePlotData(&MyPlot,"test.dat",&MyData,5);
  /*
    Later: add option to use these commands by default
    set data style linespoints
    replot
    plot ".dat" using 1:3*/
    gp = OpenGnuPlot();
    ShowPlot(&MyPlot,gp);    
    CloseGnuPlot(gp);
    check_free(MyPlot.plots);
  }
}
#endif
