/*  AllConversions3_template3.c

  Template file for creating AllConversions3.c, using 
  /projects/cold_creek/grid/watershed/convert_files.pl.

  Mark Wigmosta's C program to convert between file formats.
  Note grid dimensions and runtime options are HARDWIRED below. 
  The grid files must be stripped down--no header lines in them.
  Therefore, you need to remove the header lines in Arc ascii
  grid files before running this program.  If you are creating a binary
  mask input for the model, be sure to replace NODATA values with 0
  using a text editor before doing the conversion.  The model needs cells
  outside the basin to have a value of 0 in the mask.  

  11-6-00.  SRW adds CharAsciiToBin_FD() to convert ascii ArcInfo flow directions to
  binary DHSVM values.  To use, set FlowDir and ArcToDHSVM_FlowDir to 1 below.  
  
  11-16-00.  SRW adds code to translate veg type and soil type files.

  01-11-01.  MSW adds code to convert soil and veg type files from char's to short's

  01-26-01.  MSW subroutine CharAsciiToBin_FD: changed iTemp values in Arc to DHSVM integer 
             flowdirection switch to be consistant with ordering in InitConstants.c

  1-30-01.  SRW adds the original iTemp formulation back into code.  The original
            formulation from 11-6-00 is correct for the x, y coordinate system where
            y increases downward (origin upper left corner of grid).  Mark's 1-26-01 
            version is correct for origin in the lower left corner of grid.  Comment
            out the version not needed.

  08/14/02.  SRW adds capability to do DEM and flowdirection for the lower boundary of the
             revised DHSVM.
  
*/

#include<math.h>
#include<stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ArrayBuilder.h"

#define MAXLENGTH 100
#define NUMY NUMROWS  /* rows: 1 for east and west; 120 for north and south */
#define NUMX NUMCOLS   /* cols: 1 for north and south; 120 for east and west  */
#define NDIRS 8

void FileError( char name[MAXLENGTH] );
void CharBinToAscii( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements );
void FloatBinToAscii( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements );
void CharAsciiToBin( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements);
void CharAsciiToBin_FD( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements);
void FloatAsciiToBin( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements );
void CharBinToShortBin( char bin_name[MAXLENGTH], char bin2_name[MAXLENGTH], int elements );

int main()
{
  char dem_asc[MAXLENGTH], dem_bin[MAXLENGTH];
  char dem_gw_asc[MAXLENGTH], dem_gw_bin[MAXLENGTH];
  char mask_asc[MAXLENGTH], mask_bin[MAXLENGTH];
  char flowdir_asc[MAXLENGTH], flowdir_bin[MAXLENGTH];
  char flowdir_gw_asc[MAXLENGTH], flowdir_gw_bin[MAXLENGTH];
  char soildepth_asc[MAXLENGTH], soildepth_bin[MAXLENGTH];
  char vegtype_bin[MAXLENGTH], vegtype_char[MAXLENGTH], vegtype_asc[MAXLENGTH];
  char soiltype_bin[MAXLENGTH], soiltype_char[MAXLENGTH], soiltype_asc[MAXLENGTH];

  /* set which input files to convert */
  int BinToAscii = DO_BIN_TO_ASCII;
  int AsciiToBin = DO_ASCII_TO_BIN;
  int CharToShort = DO_CHAR_TO_SHORT;  /* Set to 1 if working with veg type or soil type */
  int FlowDir = DO_FLOWDIR;      /* Set to 1 if working with any type of flow direction file  */
  int FlowGwDir = DO_GW_FLOWDIR;      /* Set to 1 if working with any type of flow direction file  */
  int ArcToDHSVM_FlowDir = DO_ARC_TO_DHSVM_FLOWDIR;  /* Set to 1 if translating an Arc flowdirection file. */
  int Dem = DO_DEM;
  int Dem_gw = DO_GW_DEM;
  int Mask = DO_MASK;
  int VegType = DO_VEGTYPE;
  int SoilType = DO_SOILTYPE;
  int SoilDepth = DO_SOILDEPTH;

  /* set file names   These names don't have to be valid if file not selected above.  */
  strcpy(mask_asc,"MASK_ASCII");
  strcpy(mask_bin,"MASK_BIN");
  strcpy(dem_asc,"DEM_ASCII");
  strcpy(dem_bin,"DEM_BIN");
  strcpy(dem_gw_asc,"DEM_GW_ASCII");
  strcpy(dem_gw_bin,"DEM_GW_BIN");
  strcpy(flowdir_asc,"FLOWDIR_ASCII");
  strcpy(flowdir_bin,"FLOWDIR_BIN");
  strcpy(flowdir_gw_asc,"FLOWDIR_GW_ASCII");
  strcpy(flowdir_gw_bin,"FLOWDIR_GW_BIN");
  strcpy(vegtype_asc,"VEGTYPE_ASCII");
  strcpy(vegtype_bin,"VEGTYPE_BIN");
  strcpy(vegtype_char,"VEGTYPE_CHAR");
  strcpy(soiltype_asc,"SOILTYPE_ASCII");
  strcpy(soiltype_bin,"SOILTYPE_BIN");
  strcpy(soiltype_char,"SOILTYPE_CHAR");
  strcpy(soildepth_asc,"SOILDEPTH_ASCII");
  strcpy(soildepth_bin,"SOILDEPTH_BIN");

  if(BinToAscii) {
    if( FlowDir )CharBinToAscii( flowdir_bin, flowdir_asc, NDIRS*NUMX*NUMY );
    if( FlowGwDir )CharBinToAscii( flowdir_gw_bin, flowdir_gw_asc, NDIRS*NUMX*NUMY );
    if( Mask )CharBinToAscii( mask_bin, mask_asc, NUMX*NUMY );
    if( Dem )FloatBinToAscii( dem_bin, dem_asc, NUMX*NUMY );
    if( Dem_gw )FloatBinToAscii( dem_gw_bin, dem_gw_asc, NUMX*NUMY );
    if( SoilDepth )FloatBinToAscii( soildepth_bin, soildepth_asc, NUMX*NUMY );
    if( VegType )CharBinToAscii( vegtype_bin, vegtype_asc, NUMX*NUMY );
    if( SoilType )CharBinToAscii( soiltype_bin, soiltype_asc, NUMX*NUMY );
  }

  if(AsciiToBin) {
    if( FlowDir && !(ArcToDHSVM_FlowDir))
		CharAsciiToBin(flowdir_bin, flowdir_asc, NDIRS*NUMX*NUMY);
	if( FlowDir && ArcToDHSVM_FlowDir )
		CharAsciiToBin_FD(flowdir_bin, flowdir_asc, NUMX*NUMY);
    if( FlowGwDir && !(ArcToDHSVM_FlowDir))
		CharAsciiToBin(flowdir_gw_bin, flowdir_gw_asc, NDIRS*NUMX*NUMY);
	if( FlowGwDir && ArcToDHSVM_FlowDir )
		CharAsciiToBin_FD(flowdir_gw_bin, flowdir_gw_asc, NUMX*NUMY);
    if( Mask )CharAsciiToBin( mask_bin, mask_asc, NUMX*NUMY );
    if( Dem )FloatAsciiToBin( dem_bin, dem_asc, NUMX*NUMY );
    if( Dem_gw )FloatAsciiToBin( dem_gw_bin, dem_gw_asc, NUMX*NUMY );
    if( SoilDepth )FloatAsciiToBin( soildepth_bin, soildepth_asc, NUMX*NUMY );
    if( VegType )CharAsciiToBin( vegtype_char, vegtype_asc, NUMX*NUMY );
    if( SoilType )CharAsciiToBin( soiltype_char, soiltype_asc, NUMX*NUMY );
  }

  if(CharToShort) {
    /*  *type_char is the input binary file; *type_bin is the output (final, model-ready) file */
    if( VegType) CharBinToShortBin(vegtype_char, vegtype_bin, NUMX*NUMY);
    if( SoilType) CharBinToShortBin(soiltype_char, soiltype_bin, NUMX*NUMY);
  }

}  /* end of main()  */


/* CharBinToShortBin(): convert char binary to short int binary data *******************************/
void CharBinToShortBin( char bin_name[MAXLENGTH], char bin2_name[MAXLENGTH], int elements )
{
  FILE *BinaryFile;
  short int *Vec2;
  unsigned char *Vec;
  int n, NumRead = 0, NumWrite = 0;

  Vec = Build1DUChar( elements );	/* Allocate temp memory  */

  /* read char binary values */
  if((BinaryFile = fopen( bin_name, "rb")) == NULL)
    FileError( bin_name );
  
  NumRead = fread( Vec, sizeof(unsigned char), elements, BinaryFile);
	if( NumRead != elements ){
	  fprintf(stderr, "Error: %d unsigned char's Read\n", NumRead);
  }

	fclose( BinaryFile );

  Vec2 = Build1DShortInt( elements );

	/************* write short int binary values ***/
  if( (BinaryFile=fopen(bin2_name,"wb")) == NULL)
    FileError( bin2_name );

  for( n = 0; n < elements; n++ ) Vec2[n] = (short int)Vec[n];

  NumWrite = fwrite( Vec2, sizeof(short int), elements, BinaryFile);
	if( NumWrite != elements ){
	  fprintf(stderr, "Error: %d short ints written\n", NumWrite);
  }


  fclose( BinaryFile );

  Free1DUChar( Vec );
  Free1DShortInt( Vec2 );
  printf("Created file %s\n", bin2_name); 
}

/* CharBinToAscii(): convert binary to ascii data *******************************/
void CharBinToAscii( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements )
{
  FILE *BinaryFile, *AsciiFile;
  unsigned char *Vec;
  int n, NumRead = 0;

  Vec = Build1DUChar( elements );	/* Allocate temp memory  */

  /* read binary values */
  if((BinaryFile = fopen( bin_name, "rb")) == NULL)
    FileError( bin_name );
  
  NumRead = fread( Vec, sizeof(unsigned char), elements, BinaryFile);
	if( NumRead != elements ){
	  fprintf(stderr, "Error: %d unsigned char's Read\n", NumRead);
  }

	fclose( BinaryFile );

	/************* write ascii values ***/
  if( (AsciiFile=fopen(asc_name,"wt")) == NULL)
    FileError( asc_name );

  for( n = 0; n < elements; n++ ) fprintf(AsciiFile, " %d", Vec[n]);
    fprintf(AsciiFile, " \n");

  fclose( AsciiFile );

  Free1DUChar( Vec );
}


/* FloatBinToAscii(): convert binary to ascii data *******************************/
void FloatBinToAscii( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements )
{
  FILE *BinaryFile, *AsciiFile;
  float *Vec;
  int n, NumRead = 0;

  Vec = Build1DFloat( elements );	/* Allocate temp memory  */

  /* read binary values */
  if((BinaryFile = fopen( bin_name, "rb")) == NULL)
    FileError( bin_name );
  
  NumRead = fread( Vec, sizeof(float), elements, BinaryFile);
	if( NumRead != elements ){
	  fprintf(stderr, "Error: %d unsigned char's Read\n", NumRead);
  }

	fclose( BinaryFile );

	/************* write ascii values ***/
  if( (AsciiFile=fopen(asc_name,"wt")) == NULL)
    FileError( asc_name );

  for( n = 0; n < elements; n++ ) fprintf(AsciiFile, " %f", Vec[n]);
    fprintf(AsciiFile, " \n");

  fclose( AsciiFile );

  Free1DFloat( Vec );
}


/* CharAsciiToBin(): convert binary to ascii data *******************************/
void CharAsciiToBin( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements)
{
  FILE *BinaryFile, *AsciiFile;
  unsigned char *Vec;
  int n, iTemp, NumWrite = 0;

  Vec = Build1DUChar( elements );	/* Allocate temp memory  */
    
  /* read ascii values *************/
  if( (AsciiFile=fopen(asc_name,"rt")) == NULL)
    FileError( asc_name );

  for( n = 0; n < elements; n++ )
  {
    fscanf(AsciiFile, " %d", &iTemp);
    Vec[n] = (unsigned char)iTemp;
  }

  fclose( AsciiFile );

  /* write binary values */
  if((BinaryFile = fopen( bin_name, "wb")) == NULL)
    FileError( bin_name );
  
  NumWrite = fwrite( Vec, sizeof(unsigned char), elements, BinaryFile);
	if( NumWrite != elements ){
	  fprintf(stderr, "Error: %d unsigned char's Read\n", NumWrite);
  }

	fclose( BinaryFile );

  Free1DUChar( Vec );
}


/* CharAsciiToBin_FD(): convert binary to ascii data, and convert from Arc to DHSVM
   flow direction values.  Note this function reads an Arc ascii file, which has 
   one value for each grid cell:  elements = Nrows * Ncols.  
   The output *.bin file has NDIRS*Nrows*Ncols in it.  
*/
void CharAsciiToBin_FD( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements)
{

  FILE *BinaryFile, *AsciiFile;
  int i, n, cell, NumWrite, iTemp;
  unsigned char value, FlowDirData[NDIRS*NUMX*NUMY] = {0};
  value = 255;
 
  /* open files  */
  /* input (Arc flowdirection grid, in ASCII format)  */
  if( (AsciiFile=fopen(asc_name,"rt")) == NULL)
		fprintf(stderr, "Could not open Ascii Input file/n");

  /* output (binary format input for DHSVM's ReadFlowDirs() )  */
  if( (BinaryFile=fopen(bin_name,"wb")) == NULL)
		fprintf(stderr, "Could not open Binary Output file/n");

  cell = 0;
  for(i = 0; i < elements; i++)  {

	/*  read Arc's flow direction value for the cell  */
	fscanf(AsciiFile, " %d\n", &iTemp);

	/* Translate from Arc to DSHVM integer flowdirection  */
    /* This version is correct for a lower-left origin for x and y;
       i.e., y increases UPWARD.  */
/*  	switch(iTemp)  { */
/*  		case 1:   iTemp = 3; break;	 */	 /* E */
/*  		case 2:   iTemp = 4; break;	 */	 /* SE */
/*  		case 4: iTemp = 5; break;	 */	 /* S  */
/*  		case 8:  iTemp = 6; break;	 */	 /* SW */
/*  		case 16:  iTemp = 7; break;	 */	 /* W */ 
/*  		case 32:  iTemp = 0; break;	 */	 /* NW */
/*  		case 64:   iTemp = 1; break; */	 /* N */
/*  		case 128:   iTemp = 2; break; */ /* NE */
/*  		case -9999:   iTemp = -9999; break; */
/*  		default:  printf("Error in flowdirection translation %d:\n"); exit(1); */
/*  	} */

    /* This version is correct for an upper-left origin for x and y;
       i.e., y increases DOWNWARD.  As of 1/29/01, this is the way PNNL's
       version of DHSVM works.  */
	switch(iTemp)  {
		case 8:  iTemp = 0; break;		/* SW */
		case 4: iTemp = 1; break;		/* S  */
		case 2:   iTemp = 2; break;		/* SE */
		case 1:   iTemp = 3; break;		/* E */
		case 128:   iTemp = 4; break;	/* NE */
		case 64:   iTemp = 5; break;	/* N */
		case 32:  iTemp = 6; break;		/* NW */
		case 16:  iTemp = 7; break;		/* W */
		case -9999:   iTemp = -9999; break;
		default:  printf("Error in flowdirection translation.\n");
	}

	/* write 0 or 255 for each of NDIRS for the cell  */
    for( n = 0; n < NDIRS; n++ )  {
      if( n == iTemp  )  {
        FlowDirData[cell] = value;
      }
      else  {
        FlowDirData[cell] = 0;
      }
      cell++;
    }
  }

  fprintf(stderr, "Finished Reading Ascii data. \n");

  NumWrite = fwrite( FlowDirData, sizeof( unsigned char ), NDIRS*elements, BinaryFile );

  fprintf(stderr, "Wrote %d Binary Values (= NDIRS*elements).\n", NumWrite); 

  fclose(BinaryFile);
  fclose(AsciiFile); 
}  /*  end of CharAsciiToBin_FD() */


/* FloatAsciiToBin(): convert binary to ascii data *******************************/
void FloatAsciiToBin( char bin_name[MAXLENGTH], char asc_name[MAXLENGTH], int elements )
{
  FILE *BinaryFile, *AsciiFile;
  float *Vec;
  float fTemp;
  int n, NumWrite = 0;

  Vec = Build1DFloat( elements );	/* Allocate temp memory  */
    
  /* read ascii values *************/
  if( (AsciiFile=fopen(asc_name,"rt")) == NULL)
    FileError( asc_name );

  for( n = 0; n < elements; n++ )
  {
    fscanf(AsciiFile, " %f", &fTemp);
    Vec[n] = fTemp;
  }

  fclose( AsciiFile );

  /* write binary values */
  if((BinaryFile = fopen( bin_name, "wb")) == NULL)
    FileError( bin_name );
  
  NumWrite = fwrite( Vec, sizeof(float), elements, BinaryFile);
	if( NumWrite != elements ){
	  fprintf(stderr, "Error: %d float's Read\n", NumWrite);
  }

	fclose( BinaryFile );

  Free1DFloat( Vec );
}



/************** FileError(): report file I/O error and exit program **************/
void FileError( char name[MAXLENGTH] )
{
      fprintf(stderr, "ERROR - file did not open: %s\n", name);
      exit(1);
}










