/*   -*- coding: utf-8 -*-  */
/*********************************************************************
 *
 *  module   : Hfd 
 *  fichier  : HfdBuild.c
 *  Auteur   : Jacques DUCLOY
 *  Date     : Décembre 2014

 *********************************************************************
 *
 * Copyleft Ducloy
 *
 *********************************************************************/
/**
   @file

   @brief HfdBuild command

   @section HfdBuildSYNOPSIS SYNOPSIS

   @code
   HfdBuild [-s] -h hfd_name [-f descriptor][-z]
   @endcode

   @section HfdBuildDESCRIPTION DESCRIPTION

   @p HfdBuild transforms a stream of records into a hfd file the
   organisation of which is described by DamHfd(5).


   @section HfdBuildOPTIONS OPTIONS
   
   @p -s (skip key) skips the beginning of each record (until tab).

   @p -h @p hfd_name is the root name of the resulting hfd file.

   @p -f @p hfd_descriptor is a stream containing hfd description (if
   omitted a default descriptor corresponding to Ilib Hfd structure is
   taken).

   @p -z to compress the hfd file. Needs @c find, @c xargs and @c gzip in @c /usr/bin


   @section HfdBuildEXAMPLES EXAMPLES

   Let file @p struct be:
   @code
   <hfd>
     <struct>
       <dir>
         <digit>ABC
	 <digit>123
       </dir>
       <dir>
         <digit>abc
	 <digit>123
       </dir>
       <file>
         <digit>xy
	 <digit>01
       </file>
       <key>
         <digit>01
	 <digit>05
       </key>
     </struct>
   </hfd>
   @endcode

   The following command:
   @code
   HfdBuild -h resul -f struct
   @endcode

   on file:
   @code
   <a>aaaaaaa</a>
   <a>bbbbbbb</a>
   <a>ccccccc</a>
   <a>ddddddd</a>
   <a>eeeeeee</a>   
   @endcode

   will produce:
   @code
   resul.hfd/
            A1.dd/
	         a1.dd/
		      x0.df
                         A1a1x000  <a>aaaaaaa</a>
                         A1a1x005  <a>bbbbbbb</a>
                         A1a1x010  <a>ccccccc</a>
                         A1a1x015  <a>ddddddd</a>
		      x1.df
                         A1a1x100  <a>eeeeeee</a>
   @endcode

   @see DamHfd(5), DamHfdMulti(1)

   @author &copy; INIST-CNRS
   @author Jacques DUCLOY, Dominique BESAGNI, P. CHARPENTIER
           <DilibMaster@inist.fr>
   @since  1993
   @return 0 if OK
   @return 1 if the arguments were not good

*/

#include <stdlib.h>	/* getopt + system */
#include <unistd.h>	/* getopt */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "SxPath.h"
#include "Hfd.h"
void perror();

/******************* les options **********************************/
static int optionSkipKey;
static int optionCompress;
/******************* le controle de l'entrée **********************/

/* static int InputEOF_HasBeenFound=NULL; */
static int InputEOF_HasBeenFound=0;
static FILE *InputFile;

int InputNextRecord()
{
  int c; /*char c;*/
  if (InputEOF_HasBeenFound) return 0 /*NULL*/;
  if ((c=getc(InputFile))==EOF) 
     {
       InputEOF_HasBeenFound=1;
       return 0; /* return NULL; */
     };
  if (c=='\n') return InputNextRecord();
  ungetc(c,InputFile);
  return 1;
} /* InputNextRecord() */

void InputRecordCopyOnHfd(HfdHcb *hcb)
{
  int c; /*char c;*/
  int tabHasBeenFounded;

  if  (optionSkipKey==1)
    {
      tabHasBeenFounded=0;
    }

  while ((c=getc(InputFile))!=EOF)
    {  
      if  (optionSkipKey==1)
	 {
	   if(tabHasBeenFounded==0)
	     {
	       if(c=='\t')tabHasBeenFounded=1;
	     }
	   else fputc(c,HfdHcbFile(hcb));
	 }
      else fputc(c,HfdHcbFile(hcb));
      if (c=='\n') return;
    }

  fputc('\n', HfdHcbFile(hcb));
  InputEOF_HasBeenFound=1;
} /* InputRecordCopyOnHfd() */

int InputWriteNextRecordOnHfd(HfdHcb *hcb)
{
  if (InputNextRecord())
    {
      fputs(HfdHcbRecordPathNextKey(hcb),HfdHcbFile(hcb));
      fputc('\t',HfdHcbFile(hcb));
      InputRecordCopyOnHfd(hcb);
      return 1;
    }
  else return 0; /*return NULL; */
} /* InputWriteNextRecordOnHfd() */

/*******************************************************************/
HfdHcb *HfdBuild(SxmlNode *desc, char *root, char mode)
{
  HfdHcb *newHCB;
  SxmlNode *desc1;
  SxmlNode *nState;
  int nrec;
  char bufNum[20];

  desc1=SxmlClone(desc);
  SxmlAppendChild(desc1, SxmlLeafCreate("name",root));
  newHCB= HfdHcbCreate(desc1);

  nState= SxmlAppendChild(HfdHcbDesc(newHCB), SxmlLeafCreate("state","creating"));
  HfdHcbPrint(newHCB);

  mkdir(HfdHcbRootPath(newHCB),newHCB->umask);
  HfdHcbListDirFirstDir(newHCB);

  nrec=0;

  HfdHcbFilePathFirstFile(newHCB);
  if (InputNextRecord())
    {
      fputs(HfdHcbRecordPathFirstKey(newHCB), HfdHcbFile(newHCB));
      fputc('\t',HfdHcbFile(newHCB));
      InputRecordCopyOnHfd(newHCB);
      nrec++;
    };
 
  while (InputWriteNextRecordOnHfd(newHCB)){nrec++;};

  fclose(HfdHcbFile(newHCB));

  SxmlAppendChild (HfdHcbDesc(newHCB),SxmlLeafCreate("lastkey", HfdHcbLastKey(newHCB)));
  sprintf(bufNum,"%d",nrec);
  SxmlAppendChild(HfdHcbDesc(newHCB), SxmlLeafCreate ("nrec",bufNum));
  SxmlLeafSetText(nState,"created");
  HfdHcbPrint(newHCB);

  return newHCB;
} /* HfdBuild() */

/**************************************************************************/

    int getopt();
    extern char *optarg;

void usage()
{
  perror ("usage: HfdBuild [-s] -h hfd_name [-f descriptor]\n");
  exit(1);
}

int main(int argc, char **argv)
{

  HfdFile  *hfdModele;
  SxmlNode *hfdDesc;
  char     *hfdName;
  char     *sysCommand;
  int       cod_arg;

  optionSkipKey=0;
  optionCompress=0;

  hfdDesc=SxmlFromString("<hfd><struct><dir><digit>0123456789ABCDRF</digit><digit>0123456789ABCDEF</digit></dir><file><digit>0123456789ABCDEF</digit><digit>0123456789ABCDEF</digit></file><key><digit>0123456789</digit><digit>0123456789</digit></key></struct></hfd>");

  if (argc<2)usage();

    while ((cod_arg = getopt(argc,argv,"bf:h:s:z"))!=EOF)
      {
	switch(cod_arg) {
	case 'b':
	  hfdDesc=SxmlFromString("<hfd><struct><dir><digit>0123456789ABCDRF</digit><digit>0123456789ABCDEF</digit></dir><dir><digit>0123456789ABCDEF</digit><digit>0123456789ABCDEF</digit></dir><file><digit>0123456789</digit><digit>0123456789</digit></file><key></key></struct></hfd>");
	  break;
	case 'f' : 
	  hfdModele=HfdFileCreate();
	  HfdFileOpen(hfdModele,optarg);
	  hfdDesc=HfdFileNextSxml(hfdModele);
	  HfdFileClose(hfdModele);
	  break;
	case 'h' :
	  hfdName=HfdGetPath(optarg, 'r', 'A');
	  break;
	case 's' :
	  optionSkipKey=1;
	  break;
	case 'z':
	  optionCompress=1;
	  break;
	default: usage();
	  break;
     }};
  InputFile=stdin;

  HfdBuild(hfdDesc,hfdName,'w');

  if(optionCompress) {
    sysCommand=malloc(sizeof(char)*(strlen(hfdName)+80));
    sprintf(sysCommand,
	    "/usr/bin/find %s.hfd -name \"*.df\" | /usr/bin/xargs /usr/bin/gzip ",
	    hfdName);
    system(sysCommand);
    free(sysCommand);
  }

  return 0;
}
