/*
 * $Id: gplot2.cxx,v 4.2 2004/06/17 17:34:18 hut66au Exp $
 *
 * Imview, the portable image analysis application
 * http://www.cmis.csiro.au/Hugues.Talbot/imview
 * ----------------------------------------------------------
 *
 *  Imview is an attempt to provide an image display application
 *  suitable for professional image analysis. It was started in
 *  1997 and is mostly the result of the efforts of Hugues Talbot,
 *  Image Analysis Project, CSIRO Mathematical and Information
 *  Sciences, with help from others (see the CREDITS files for
 *  more information)
 *
 *  Imview is Copyrighted (C) 1997-2001 by Hugues Talbot and was
 *  supported in parts by the Australian Commonwealth Science and 
 *  Industry Research Organisation. Please see the COPYRIGHT file 
 *  for full details. Imview also includes the contributions of 
 *  many others. Please see the CREDITS file for full details.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
 * */

/*
  ImView's interface to gnuplot, after similar work for EiC by
  Ed Breen
  Example usages:
  #include gplot2.c
  plot_t *p1 = openplot("p1");
  send2plot(p1,"plot sin(x) + tan(x)");
  closeplot(p1);
*/   

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include "gplot2.hxx"
#include "imview.hxx"
#include "machine.hxx"

using std::list;

static list <char *>  gplottmpnamelist;

void Send_2_plot_(plot_t *p, char * fmt, ...)
{
    char *buff;
    int   stringlength, allocatelength;
    va_list args;

    stringlength = strlen(fmt)*2;
    allocatelength = (512 > stringlength) ? 512:stringlength;
    buff = (char *)malloc(allocatelength); /* fmt string can be VERY long... */

    im_va_start(args,fmt);
    
    vsprintf(buff,fmt,args);

    fputs(buff,getPlotFile(p));
    fputc('\n',getPlotFile(p));

    free(buff);
    va_end(args);
}

void plotDoubles(double *hist, int n,plot_t *p, bool smooth)
{
    int i;
    double min,max;
    FILE *fp;

    fp = fopen(p->fname,"w");
    min = max = *hist;
    for(i=0;i<n;++i,++hist) {
        if(*hist < min)
            min = *hist;
        if(*hist > max)
            max = *hist;
        fprintf(fp,"%d %g\n",i,*hist);
    }
    fclose(fp);

    Send_2_plot_(p,"plot [0:%d] '%s' %s notitle with lines",
		 n-1, p->fname,
		 smooth ? "smooth csplines":"" );
}



static void addToUnlinkList(char *tmpname)
{
    dbgprintf("Adding %s to the list of files to remove later\n", tmpname);
    gplottmpnamelist.push_back(tmpname);
}

static void unlinkAllTmpFiles(void)
{
    while (!gplottmpnamelist.empty()) {
	char *&nameref = gplottmpnamelist.back();
	remove(nameref);
	dbgprintf("Removing %s\n", nameref);
	// this name had been allocated
	free(nameref);
	gplottmpnamelist.pop_back();
    }
}

// Use this in conjunction with dataMPlot
char *writeDoubleVector(double *vec, int n)
{
    char * tmpName = tempnam(NULL, "FlIm"); // this allocates a new area
    FILE *fp = tmpfile();
    int i;

    fp = fopen(tmpName,"w");
    if(!fp)
        return NULL;
    for(i=0;i<n;++i)
        fprintf(fp,"%d %g\n",i,vec[i]);
    
    fclose(fp);
    addToUnlinkList(tmpName);
    return tmpName;
}

// allows multiple plots on the same plot
void dataMPlot(plot_t *p,
               char * (*f)(...),  /* return the name of the file where data is stored  */
               int nv,         /* number of vectors in vecs */
               void **vecs,    /* array of vectors */
	       char **labels,  /* arrays of labels (may not be NULL) */
               int *lens,      /* array of lengths to vecs */   
	       bool smooth)   /* uses splines or straight lines */
{

    /* Assumes that plot title, line style etc  have been
       handled elsewhere.
    */
    char *buff;
    char buf[256];
    int blen = 256;
    char **names = (char **) malloc(nv * sizeof(char*));    
    char *tmp;
    int i,k, tl = 0;

    
    for(i=0;i<nv;i++) {
        tmp = f(vecs[i],lens[i]);
        k = strlen(tmp);
        names[i] = (char *)malloc(k+1);
        tl += k + 5;
        strcpy(names[i],tmp);
    }
    buff = (char *)malloc(blen+tl);
    
    sprintf(buff,"plot '%s' title '%s'",names[0], labels[0]);
    free(names[0]);
    for(i=1;i<nv; i++) {
        sprintf(buf,",'%s' title '%s'",names[i], labels[i]);
        strcat(buff,buf);
        free(names[i]);
    }
    send2plot(p,buff);
    free(names);
    free(buff);
}


void * closePlot(plot_t *p)
{
    if(p != NULL) {
	fflush(p->fp);
        pclose(p->fp);
        remove(p->fname);
        free(p);
    }
    unlinkAllTmpFiles();
    return NULL;
}


plot_t * openPlot(char * plotname)
{
    plot_t * plot = (plot_t*)calloc(sizeof(plot_t),1);

    if(plot != NULL) {
        if ((plot->fp = popen("gnuplot","w")) != 0) {
	    setvbuf(plot->fp,NULL,_IONBF,0); // unbuffered I/O
	    if(plotname != NULL) {
		Send_2_plot_(plot,"set title '%s'",plotname);
	    }
	    tmpnam(plot->fname);
	} else {
	    free(plot);
	    plot = NULL;
	}
    }
    return plot;
}



