/*----------------------------------------------------------------*
 *
 * File : doDecoding.c
 * Author : NTM
 * Created : 01/04/05
 *
 *
 * Copyright (C) Nicolas Thierry-Mieg, 2006.
 *
 *
 * This file is part of InterPool, written by 
 * Nicolas Thierry-Mieg (CNRS, France) Nicolas.Thierry-Mieg@imag.fr
 *
 * InterPool 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.
 *
 * InterPool 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 InterPool; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *-----------------------------------------------------------------*/

#include <stdlib.h> /* exit, atoi */
#include <stdio.h> /* printf and friends */
#include <string.h> /* strncpy, strlen */
#include <limits.h> /* CHAR_BIT */

#include <sys/stat.h> /* for mkdir */
#include <sys/types.h> /* also for mkdir */
#include <errno.h> /* for mkdir return status */

#include "types.h" /* MOT, ARCH */
#include "config.h" /* OUTDIR */
#include "jobs.h" /* JobIdentReal, OUTFILELENGTH */
#include "decodeObservedSig.h" /* decodeObservedSig */

/*!
  \file doDecoding.c
  \brief This file defines the main function to decode an observed signature.
*/


/************************************************************************
 ******************* LOCAL FUNCTIONS ************************************
 ************************************************************************/

/********************** DECLARATIONS ************************************/

/************************ BODIES ***************************************/



/************************************************************************
 ****************************** MAIN ************************************
 ************************************************************************/

/*! 
  \brief main function to decode an observed signature.

  Usage is: ipoolDecoding n nbPools designFile sigFile
*/
int main(int argc, char* argv[])
{
  /* test if ARCH corresponds to the MOT size */
  if (ARCH != sizeof(MOT)*CHAR_BIT)
    {
      fprintf(stderr, 
	      "ARCH is not in accord with MOT (both defined in types.h)!\n") ;
      fprintf(stderr, "You must change one or the other and recompile.\n") ;
      fprintf(stderr, "ARCH should correspond to your architecture for optimal performance.\n") ;
      exit(1) ;
    }
  
  if (argc != 5)
    {
      fprintf(stderr, "wrong number of args.\n") ;
      fprintf(stderr, "USAGE: ipoolDecoding n nbPools designFile sigFile\n") ;
      fprintf(stderr, "n: number of variables,\nnbPools: number of pools,\n") ;
      fprintf(stderr, "designFile: a design file in interPool format,\n") ;
      fprintf(stderr, "sigFile: a signature in V 2.0 (XML) format\n") ;
      fprintf(stderr, "The formats for designFile and sigFile are documented in the README.\n") ;
      exit(1) ;
    }

  int n = atoi(argv[1]) ;
  int nbPools = atoi(argv[2]) ;

  /* design file name */
  char designFile[OUTFILELENGTH] ;

  (void)strncpy(designFile, argv[3], OUTFILELENGTH) ;
  // make sure file name was not too long
  if (designFile[OUTFILELENGTH-1] != '\0')
    {
      fprintf(stderr, "in doDecoding.c, error building designFile: too long?\n");
      exit(1);
    }

  /* input (signature) file name */
  char sigFile[OUTFILELENGTH] ;

  (void) strncpy(sigFile, argv[4], OUTFILELENGTH) ;
  // make sure file name was not too long
  if (sigFile[OUTFILELENGTH-1] != '\0')
    {
      fprintf(stderr, "in doDecoding.c, error building sigFile: too long?\n");
      exit(1);
    }

  /* check some parameters */
  if (n <= 0)
    {
      fprintf(stderr, "in doDecoding.c: n must be positive\n") ;
      exit(1) ;
    }
  if (nbPools <= 0)
    {
      fprintf(stderr, "in doDecoding.c: nbPools  must be positive\n") ;
      exit(1) ;
    }

  /* make the OUTDIR directory if it doesn't exist */
  {
    /* create output directory with perms 755 if it doesn't exist */
    extern int errno ;
    int status = mkdir(OUTDIR, 511) ;
    if (status !=0)
      { /* if dir just already existed, continue; else die */
	if (errno != EEXIST)
	  {
	    fprintf(stderr, "Error creating directory OUTDIR\n") ;
	    exit(1) ;
	  }
      }
  }

  /* build output filename */
  char outFileName[OUTFILELENGTH] ;

    /* get rid of the path in sigFile: */
    /* initially, point baseName to the last char */
    char* baseName = sigFile + strlen(sigFile) ;
    while((baseName != sigFile) && (*(baseName-1) != '/'))
      baseName-- ;

    /* check that we found something */
    if (baseName == sigFile + strlen(sigFile))
      {
	fprintf(stderr, "in ipoolDecoding: sigFile can begin with a path, but must have a file name.\n") ;
	exit(1) ;
      }

  /* OK, build outFileName */
  int numchars = snprintf(outFileName,OUTFILELENGTH,"%s/%s.Decoded",
			  OUTDIR,baseName);
  // make sure file name was not too long
  if ((numchars < 0) || (numchars >= OUTFILELENGTH))
    {
      fprintf(stderr, "in main, error building outFileName: too long?\n");
      exit(1);
    }

  /* set values for the parameters to simulation: build a JobIdentReal */
  JobIdentReal thisJob ;

  thisJob.n = n ;
  thisJob.nbPools = nbPools ;
  thisJob.designFileName = designFile ;
  thisJob.inFileName = sigFile ;
  thisJob.outFileName = outFileName ;

  /* mode: choose solvexp method to use. Current valid values are:
     - 1 (noisyNaive)
     - 4 (noisyClosureReal, regular Rec algo)
     - 5 (noisyClosureReal, improved RecSubstracted algo)
     The best method is RecSubstracted, so just use mode=5. */
  int mode = 5 ;

  /* launch the job */
  decodeObservedSig(&thisJob, mode) ;

  return 0;
}

