/**********************************************************************
*
*  projet   : Infometrics
*  module   : Histo
*  commande : HistoBuildRec
*  fichier  : HistoBuildRec.c
*  Auteur   : Jacques DUCLOY
*  Date     : Juillet 97
*
*********************************************************************
* Copyright (c) 1997 CNRS/CRIN & INRIA Lorraine
* 
********************************************************************/

#include "ctype.h"
#include "DamFile.h"
#include "SgmlInput.h"
#include "Histo.h"
#include <stdlib.h>

int atoi();
void perror();
#include <string.h>
int getopt();
extern char *optarg;
int flagFreq1;

void usage()
{
  perror ("usage: HistoBuildRec  [-e elementTag] [-f freqTag] [-l listTag] [-r recordTag] [-k keyTag]  \n");
  exit(1);
}
static SgmlNode *newRecordKey;
static SgmlNode *recordKey=NULL;
static SgmlNode *assocKey;
static SgmlNode *newAssocKey;
static SgmlNode *newRecord=NULL;

static char *histoTag;
static char *keyTag;
static char *listTag;
static char *assocTag;
static char *elemTag;
static char *freqTag;
static char *totalTag;

static int   freq;
static int   totalFreq;
static float floatFreq;
static float floatTotalFreq;
static char *freqFormat;
static char  strFreq[10];
static char *nElemTag;

static int assocToBePurged;

Histo* histogramme;
static int sizeHisto;
static int cutHisto;

static  char numType;

void purgeAssoc()
{
  SgmlNode *t;
  if(assocToBePurged)
    {
      if (assocTag) 
	{
	  t=SgmlCreateMark(assocTag);
	  SgmlAddSon(t, assocKey);
	}
      else t=assocKey;
      if (numType=='i')
	{
	  HistoAdd (histogramme, t, freq);
	  totalFreq+=freq;
	}
      else 
	{
	  HistoFloatAdd (histogramme, t, floatFreq);
	  floatTotalFreq+=floatFreq;
	}
      assocToBePurged=0;
    }
};

void initList()
{
  assocKey=NULL;
  assocToBePurged=0;

  if(newRecord) SgmlFree(newRecord);
  newRecord=SgmlCreateMark(histoTag);
  recordKey=SgmlCut(newRecordKey);
  totalFreq=0;
  floatTotalFreq=0;
  if (keyTag) 
    {
      SgmlNode *t;
      SgmlAddSon(newRecord, t=SgmlCreateMark(keyTag));
      SgmlAddSon(t, recordKey);
    }
  else SgmlAddSon(newRecord,recordKey);
};

void purgeList()
{
  SgmlNode *list;
  int nElemList;

  nElemList=histogramme->nElem + 1;
  purgeAssoc();
  if ((list=HistoToSgmlAndReset
       (histogramme,listTag, elemTag, freqTag, freqFormat)
       ))
    {

       if (numType=='i')
	 {
	   sprintf(strFreq,freqFormat,totalFreq);
	 }
       else 
	 {
	   sprintf(strFreq,freqFormat,floatTotalFreq);
	 }
      SgmlAddSon(newRecord, SgmlCreateLeaf(totalTag, strFreq));
      if (nElemTag)
	{
	  sprintf(strFreq, freqFormat, nElemList);
	  SgmlAddSon(newRecord, SgmlCreateLeaf(nElemTag, strFreq));
	}
      SgmlAddSon (newRecord,list  );
      SgmlPrint(newRecord);
      putchar('\n');
    }
  
};

void initAssoc()
{
  assocKey=SgmlCut(newAssocKey);
  freq=0;
  floatFreq=0;
  assocToBePurged=1;
};


void elemList()
{
  if (numType=='i')
    {
      if(flagFreq1)freq++;
      else freq+=atoi(SgmlGetFirstData(SgmlLast(SgmlInputRecord)));
    }
  else
    {
      char *s1;
      float f1;
      s1=SgmlGetFirstData(SgmlLast(SgmlInputRecord));
      sscanf(s1,"%f",&f1);
      floatFreq+=f1;
    }
};

int main(argc,argv)
     int argc;
     char **argv;
{
  int cod_arg;
  char *cutHistoStr;

  numType='i';
  histoTag="histo";
  keyTag="k";
  listTag="l";
  assocTag="a";
  elemTag="e";
  freqTag="f";
  sizeHisto=100;
  cutHisto=0;
  totalTag="t";
  flagFreq1=0;
  freqFormat="%d";
  nElemTag=NULL;

  while (((cod_arg = getopt(argc,argv,"1a:c:e:f:h:k:l:m:n:r:t:F:"))!=EOF))
    {
      switch(cod_arg) 
	{

	case '1':
	  flagFreq1=1;
	  break;

	case 'a':
	  assocTag=optarg;
	  if ((strcmp(assocTag,"0")==0))assocTag=NULL;
	  break;

	case 'c':
	  cutHistoStr=(optarg);
	  break;

	case 'e':
	  elemTag=optarg;
	  break;

	case 'f':
	  freqTag=optarg;
	  break;

	case 'h':
	case 'r':
	  histoTag=optarg;
	  break;

	case 'k':
	  keyTag=optarg;
	  if ((strcmp(keyTag,"0")==0))keyTag=NULL;
	  break;

	case 'l':
	  listTag=optarg;
	  break;
	  
	case 'm':
	  sizeHisto=atoi(optarg);
	  break;

	case 'n':
	  nElemTag=optarg;
	  break;

	case 't':
	  totalTag=optarg;
	  if ((strcmp(totalTag,"0")==0))totalTag=NULL;
	  break;

	case 'F':
	  {
	    char *fPos;
	    freqFormat=optarg;
	    fPos=strchr(optarg,'f');
	    if(fPos)numType='f';
	  }
	  break;

	default: 
	  usage();
	}
    }

  histogramme=HistoCreate(sizeHisto,numType);
  if (cutHisto)
    {
      float f1;
      if (numType=='i')HistoSetCut(histogramme, atoi(cutHistoStr));
      else 
	{
	  sscanf(cutHistoStr,"%f",&f1);
	  HistoFloatSetCut(histogramme, f1);
	}
    }
  HistoSetFreeMode(histogramme, 1);

  while(SgmlInputNextRecord())
    {
      newRecordKey=SgmlFirst(SgmlInputRecord);
      newAssocKey =SgmlNext(newRecordKey);

      if(!recordKey) 
	{
	  initList();
	  initAssoc();
	}

      else 
	{
	  if(!SgmlEqualSubTree(recordKey,newRecordKey))
	    {
	      purgeList();
	      initList();
	      initAssoc();
	    }
	  else
	    {
	      if(!SgmlEqualSubTree(assocKey,newAssocKey))
		{
		  purgeAssoc();
		  initAssoc();
		}
	    }
	}
      elemList();
    }
  purgeList();
  exit(0);
  return 0;
}

