/*
 * $Id: saveSpect.cxx,v 4.0 2003/04/28 14:40:00 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.
 * */

/*------------------------------------------------------------------------
 *
 * A save preference panel using fluid
 *
 * Hugues Talbot	27 Apr 1998
 *      
 *-----------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include "imunistd.h"
#include <string.h>
#include <errno.h>
#include <FL/Fl_File_Chooser.H>
#include <FL/fl_ask.H>
#include "imview.hxx"
#include "imageIO.hxx"
#include "imageViewer.hxx"
#include "spectraBox.hxx"
#include "profileBox.hxx"
#include "saveSpect.hxx"
#include "io/savetiff.hxx"
#include "io/saveZimage.hxx"

// 
typedef void (menucb)(Fl_Menu_ *, void *);

// application components
extern char appName[];
extern imageIO *IOBlackBox;
extern spectra     *spectraPanel;
extern profile     *profilePanel;
extern savespect   *saveSpectPanel;

static const char *formatExtensionList[4] = {
    ".tif",
    "_z",
    ".euro",
    0
};


savespect::savespect()
{
    dbgprintf("Save spectrum panel constructed\n");
    saveWindow = 0; // fluid depends on that
    return;
}


void savespect::setDefaults()
{
    static char buff[100];

    dbgprintf("Setting default for save panel\n");
    
    // default value for file
    sprintf(buff, "%s.euro", appName);
    
    filenameInput->value(buff);
    formatChoice->value(EURO_FMT);
    whichPanel = SPECTRAPANEL;
    
    return;
}


// this functions changes the .tiff in _z, etc...
void savespect::toggleExtension(int format)
{
    static char inputContent[1024]; 
    char *substr;

    strcpy(inputContent, filenameInput->value());
    
    dbgprintf("Looking for extensions\n");
    if (inputContent != 0) {
	for (int i = 0 ; formatExtensionList[i] != 0 ; i++) {
	    // look for the common extension of the format
	    if (((substr = strstr(inputContent, formatExtensionList[i])) != 0)
		&& (format < LAST_FMT)) {
		strcpy(substr, formatExtensionList[format]);
		filenameInput->value(inputContent);
		dbgprintf("Extension found\n");
		break;
	    }
	}
    }
    
    return;
}



void savespect::saveFileName(const char *fn)
{
    // this copies it to something more permanent.
    filenameInput->value(fn);
    return;
}


int savespect::doTheSaving()
{
    int retval = 0;

    dbgprintf("Doing the saving now\n");
    // we can't go any further until we have a writexxx procedure...
    const char *filename = filenameInput->value();

    // trivial user-generated possible errors
    if ((filename == 0) || (filename[0] == '\0')) {
	errprintf("Please specify a file to save to\n");
	return(1);
    } else {
	if (access(filename, W_OK) == 0) {
	    // the file already exists
	    static char alrtmsg[1024] ;
	    sprintf(alrtmsg,
		    "File %s already exists\n"
		    "Do you want to overwrite?\n",
		    filename);
	    if (fl_ask(alrtmsg) == 0) {
		// no, we don't want to overwrite...
		return(2);
	    }
	}
    }

    switch (formatChoice->value()) {
      case EURO_FMT: {
	  // this is so simple that I thought there would be
	  // no need to put this in a separate function
	  int nx = 0;

	  if (whichPanel == SPECTRAPANEL)
	      nx = spectraPanel->getNbVal();
	  else if (whichPanel == PROFILEPANEL)
	      nx = profilePanel->getNbVal();
	  
	  if (nx > 0) {
	      FILE *spct = fopen(filename, "wb");
	      if (spct != NULL) {
		  if (whichPanel == SPECTRAPANEL) {
		      double *dbuff= spectraPanel->getData();
		      fprintf(spct, "%d 1\n", nx);
		      for (int i = 0 ; i < nx ; i++) {
			  fprintf(spct, "%10.5g%c",dbuff[i],(i % 5 == 4)? '\n':' ');
		      }
		  } else if (whichPanel == PROFILEPANEL) {
		      double *rbuff = profilePanel->getDataR();
		      double *gbuff = profilePanel->getDataG();
		      double *bbuff = profilePanel->getDataB();
			  int     i;

		      if ((gbuff == 0) && (rbuff != 0)) {
			  fprintf(spct, "%d 1\n", nx);
			  for (i = 0 ; i < nx ; i++) {
			      fprintf(spct, "%10.5g%c",rbuff[i],(i % 5 == 4)? '\n':' ');
			  }
		      } else if ((rbuff != 0) && (gbuff != 0) && (bbuff != 0)) {
			  fprintf(spct, "%d 3\n", nx);
			  for (i = 0 ; i < nx ; i++) {
			      fprintf(spct, "%10.5g%c",rbuff[i],(i % 5 == 4)? '\n':' ');
			  }
			  fprintf(spct, "\n");
			  for (i = 0 ; i < nx ; i++) {
			      fprintf(spct, "%10.5g%c",gbuff[i],(i % 5 == 4)? '\n':' ');
			  }
			  fprintf(spct, "\n");
			  for (i = 0 ; i < nx ; i++) {
			      fprintf(spct, "%10.5g%c",bbuff[i],(i % 5 == 4)? '\n':' ');
			  }
		      }
		  }
		      
		  fprintf(spct, "\n");
		  fclose(spct);
	      } else
		  errprintf("Error in Euro saving code\n"
			    "while writing %s: %s\n",
			    filename, strerror(errno));
	  }
	  break;
      }

      case ZIMAGE_FMT: {
	int nx[3], ny[3], nz[3], x0[3], y0[3], z0[3], ptype[3];
	void *outbuffp[3];
	
	if (whichPanel == SPECTRAPANEL) {
	    if ((nx[0] = spectraPanel->getNbVal()) > 0) {
		nx[1] = nx[2] = 1;
		ny[0] = ny[1] = ny[2] = 1; // this is a vector
		nz[0] = nz[1] = nz[2] = 1; // not a 3D image...
		x0[0] = x0[1] = x0[2] = 0;
		y0[0] = y0[1] = y0[2] = 0;
		z0[0] = z0[1] = z0[2] = 0;
		ptype[0] = IM_DOUBLE;
		outbuffp[0] = spectraPanel->getData();
		outbuffp[1] = outbuffp[2] = 0;
		retval = save_zimage(filename, 1,
				     nx, ny, nz,
				     x0, y0, z0,
				     ptype,
				     outbuffp);
		if (retval != 0)
		    errprintf("Error in Z-IMAGE saving code\n"
			      "while writing %s: %s\n",
			      filename, strerror(errno));
	    }
	} else if (whichPanel == PROFILEPANEL) {
	    if ((nx[0] = profilePanel->getNbVal()) > 0) {
		ny[0] = ny[1] = ny[2] = 1; // this is a vector
		nz[0] = nz[1] = nz[2] = 1; // not a 3D image...
		x0[0] = x0[1] = x0[2] = 0;
		y0[0] = y0[1] = y0[2] = 0;
		z0[0] = z0[1] = z0[2] = 0;
		ptype[0] = IM_DOUBLE;
		outbuffp[0] = profilePanel->getDataR();
		outbuffp[1] = profilePanel->getDataG();
		outbuffp[2] = profilePanel->getDataB();
		if ((outbuffp[0] != 0) && (outbuffp[1] == 0) && (outbuffp[2] == 0)) {
		    nx[1] = nx[2] = 1;
		    retval = save_zimage(filename, 1,
					 nx, ny, nz,
					 x0, y0, z0,
					 ptype,
					 outbuffp);
		} else if ((outbuffp[0] != 0) && (outbuffp[1] != 0) && (outbuffp[2] != 0)) {
		    nx[1] = nx[2] = nx[0];
		    ptype[1] = ptype[2] = IM_DOUBLE;
		    retval = save_zimage(filename, 3,
					 nx, ny, nz,
					 x0, y0, z0,
					 ptype,
					 outbuffp);
		}
		    
		if (retval != 0)
		    errprintf("Error in Z-IMAGE saving code\n"
			      "while writing %s: %s\n",
			      filename, strerror(errno));
	    }
	}
	break;
      }

      case TIFF_FMT: {
	  int    pi, sf, spp, bps, nbdata;
	  int    pixeltype, imagetype;
	  int    start[2], end[2];
	  void  *outbuffp[3];

	  if (whichPanel == SPECTRAPANEL) {
	      if ((nbdata = spectraPanel->getNbVal()) > 0) {
		  // get the pixtype & imgtype
		  pixeltype = IM_DOUBLE;
		  outbuffp[0] = spectraPanel->getData();
		  outbuffp[1] = outbuffp[2] = 0;
		  imagetype = IM_SPECTRUM;
		  spp = 1;
		  setTifftype(pixeltype, imagetype, &pi, &sf, &spp, &bps);
		  if (spp != 1) {
		      errprintf("This can't happen: spp(%d) != 1\n",
				spp);
		      break;
		  }
		  start[0] = 0;
		  end[0] = nbdata -1;
		  start[1] = 0;
		  end[1] = 0;
		  retval = save_tiff(outbuffp, 0,
				     start, end,
				     pi, sf, spp, bps,
				     0, 0,
				     filename,
				     0); // always uncompressed
	      } 



	  } else {
	      int nbcomps;
	      
	      if ((nbdata = profilePanel->getNbVal()) > 0) {
		  // get the pixtype & imgtype
		  pixeltype = IM_DOUBLE;
		  outbuffp[0] = profilePanel->getDataR();
		  outbuffp[1] = profilePanel->getDataG();
		  outbuffp[2] = profilePanel->getDataB();
		  
		  if ((outbuffp[0] != 0) && (outbuffp[1] == 0) && (outbuffp[2] == 0)) {
		      imagetype = IM_SPECTRUM;
		      nbcomps = 1;
		      setTifftype(pixeltype, imagetype, &pi, &sf, &spp, &bps);
		  } else {
		      imagetype = IM_RGB;
		      nbcomps = 3;
		      setTifftype(pixeltype, imagetype, &pi, &sf, &spp, &bps);
		  }
		  spp = nbcomps;
		  if (spp != nbcomps) {
		      errprintf("This can't happen: spp(%d) != nbcomps(%d)\n",
				spp, nbcomps);
		      break;
		  }
		  start[0] = 0;
		  end[0] = nbdata -1;
		  start[1] = 0;
		  end[1] = 0;
		  retval = save_tiff(outbuffp, 0,
				     start, end,
				     pi, sf, spp, bps,
				     0, 0,
				     filename,
				     0); // always uncompressed
	      }
	  }

	  break;
      }
      
      default:
	errprintf("This format is not supported yet, sorry!\n");
	retval = 5;
	break;
    }

    return retval;
}

void savespect::show()
{
    saveWindow->show();
}

void savespect::hide()
{
    saveWindow->hide();
}


// save panel associated callbacks

void filenameinput_cb(Fl_Input *, savespect *)
{
    dbgprintf("File name input callback\n");
    return;
}


void browsebutton_cb(Fl_Button *, savespect *panel)
{
    const char *currentfile;
    static const char *p = 0;
    
    dbgprintf("Browse button pressed on save prefs panel\n");
    
    currentfile = panel->filenameInputValue();
    switch (panel->selectedFileFormat()) {
      case EURO_FMT:
	p = fl_file_chooser("Save to file", "*.[Ee][Uu][Rr][Oo]", currentfile);
	break;
      case ZIMAGE_FMT:
	p = fl_file_chooser("Save to file", "*_z", currentfile);
	break;
      case TIFF_FMT:
	p = fl_file_chooser("Save to file", "*.[tT][iI][fF]*", currentfile);
	break;
      default:
	p = fl_file_chooser("Save to file", "*", currentfile);
	break;
    }
			
    if (p) panel->saveFileName(p);
    
    return;
}

void formatchoice_cb(Fl_Choice *, savespect *)
{
    dbgprintf("Format choice menu callback\n");
    return;
}


void cancelbutton_cb(Fl_Button *, savespect *panel)
{
    dbgprintf("Cancel Button pressed on save prefs panel\n");
    // hide the window
    panel->hide();
    return;
}

void okbutton_cb(Fl_Return_Button *, savespect *panel)
{
    dbgprintf("Print Button pressed on save prefs panel\n");
    if (panel->doTheSaving() == 0) {
	// hide the window
	panel->hide();
    }
    return;
}

// callback for the choice menu

void chosenSpectFormat_cb(Fl_Menu_ *, void *fmt)
{
    long val = (long)fmt;
    
    switch (val) {
      case EURO_FMT:
	dbgprintf("Euro Format selected\n");
	break;
      case ZIMAGE_FMT:
	dbgprintf("Z-IMAGE format selected\n");
	break;
      case TIFF_FMT:
	dbgprintf("TIFF format selected\n");
	break;
    }
    saveSpectPanel->toggleExtension(val);
}

