/*   -*- coding: utf-8 -*-  */
/**********************************************************************
*
*  module   : SxmlNode
*  fichier  : SxmlGrouping.c
* Auteur   : Jacques DUCLOY
*  Date     : 2013
*
***********************************************************************/

#include <stdio.h>
#include "SxmlNode.h"
#include "Buffer.h"
#include <getopt.h>

int getopt();
extern char *optarg;

Buffer *bufInput;
Buffer *bufKey;
SxmlNode *currentGroup;
SxmlNode *currentList;
char *currentPos;
char *iTag;
int noTagI;


void createGroupRecord()
{
  char *posTab;
  char *posTab1;
  SxmlNode *n1;
  SxmlNode *n2;

  if (!(posTab=strchr(BufferString(bufInput),'\t'))) 
    {
      currentGroup=SxmlLeafCreate(iTag, BufferString(bufInput));
      return;
    }
  currentGroup=NULL;
  posTab=BufferString(bufInput);
  while ((posTab1=strchr(posTab,'\t')))
    {
      if(!currentGroup)
	{
	  currentGroup=SxmlElementCreate("g");
	  n1=currentGroup;
	  BufferStrncpy(bufKey, BufferString(bufInput), posTab1-BufferString(bufInput));
	}
      else
	{
	   SxmlAppendChild(n1,n2=SxmlElementCreate("g"));
	   n1=n2;
	}
      posTab1[0]='\0';
      SxmlAddFirstChild(n1, SxmlLeafCreate("k",posTab));
      SxmlAppendChild(n1,n2=SxmlElementCreate("l"));
      posTab=posTab1+1; 
      n1=n2;
    }
  SxmlAppendChild(n1,SxmlLeafCreate(iTag,posTab));
}

int testNewRecord()
{
  char *posTab;
  if (SxmlNodeHasName(currentGroup,iTag)) return 1;
  if (!(posTab=strchr(BufferString(bufInput),'\t'))) return 1;
  if (strncmp(BufferString(bufKey), BufferString(bufInput), 
	      posTab-BufferString(bufInput))!=0) return 1;
  currentPos=posTab+1;
  currentList=SxmlGetFirstChildByTagName(currentGroup,"l");
  return 0;
}

void insertNewTree(SxmlNode *list, char *pos)
{
  char *newPos;
  char *posTab;
  SxmlNode *newGroup;
  SxmlNode *newList;

  if(!(posTab=strchr(pos,'\t')))
    {  /*  insertion de l'élément terminal */
      SxmlAppendChild (list, SxmlLeafCreate(iTag,pos));
      return;
    }
  newPos=posTab+1;
  posTab[0]='\0';
  SxmlAppendChild(list,newGroup=SxmlElementCreate("g"));
  SxmlAppendChild(newGroup, SxmlLeafCreate("k",pos));
  SxmlAppendChild(newGroup, newList=SxmlElementCreate("l"));
  insertNewTree(newList, newPos);
  return;
}

SxmlNode *insertTree(SxmlNode *list, char *pos)
{
  char *posTab;
  SxmlNode *lastChild;
  SxmlNode *newList;
  char *newPos;
  char *kOld;
  if(!(posTab=strchr(pos,'\t')))
    {  /*  insertion d'un élément */
      SxmlAppendChild (list, SxmlLeafCreate(iTag,pos));
      return list;
    }
  lastChild=SxmlLastChild(list);
  if (SxmlNodeHasName(lastChild,iTag))
    { /* groupe après un élement */
      insertNewTree(list,pos);
      return list;
    }
 
  kOld=SxmlLeafText(SxmlGetFirstChildByTagName(lastChild,"k"));
  posTab[0]='\0';
  if (strcmp(pos,kOld)==0)
    { /* même clé */
      newList=SxmlGetFirstChildByTagName(lastChild,"l");
      newPos=posTab+1;
      insertTree(newList, newPos);
      return list;
    }
   posTab[0]='\t';
   insertNewTree(list,pos);
   return list;
}

static char  strFreq[10];

int replaceElem (SxmlNode *currentGroup)
{
  SxmlNode *listGroup;
  if (!SxmlIsElement(currentGroup)) return 0;
  if (SxmlNodeHasName(currentGroup,iTag)) 
    {
      SxmlNode *newElem;
      newElem=SxmlFirstChild(currentGroup);
      SxmlRemoveChild(newElem);
      SxmlReplaceChild(currentGroup, newElem);
      SxmlFree(currentGroup);
      return 1;
    }
  if ((listGroup=SxmlGetFirstChildByTagName(currentGroup,"l")))
    {
      SxmlNode *gOrE;
      gOrE=SxmlFirstChild(listGroup);
      while (gOrE)
	{
	  SxmlNode *nextGorE;
	  nextGorE=SxmlNextSibling(gOrE);
	  replaceElem (gOrE);
	  gOrE=nextGorE;
	}
    }
  return 1;
}

int computeFreqCount(SxmlNode *currentGroup)
{
  SxmlNode *listGroup;
  if (!SxmlIsElement(currentGroup)) return 0;
  if (SxmlNodeHasName(currentGroup,iTag)) return 1;
  if ((listGroup=SxmlGetFirstChildByTagName(currentGroup,"l")))
    {
      SxmlNode *gOrE;
      int f;
      int t;
      f=0;
      t=0;
      while ((gOrE=SxmlNextNode(listGroup)))
	{
	  f++;
	  t+=computeFreqCount(gOrE);
	}
      sprintf(strFreq, "%d", f);
      SxmlAppendChild(currentGroup, SxmlLeafCreate("n", strFreq));
      sprintf(strFreq, "%d", t);
      SxmlAppendChild(currentGroup, SxmlLeafCreate("t", strFreq));
      return t;
    }
  return 0;
}

void printGroup()
{
  if (noTagI) replaceElem (currentGroup);
  printf("%s\n", SxmlToString(currentGroup));
}

int main (int argc, char **argv)
{
  int cOption;
  
  noTagI=0;
  iTag="i";
  while((cOption=getopt(argc,argv,"i:I"))!=EOF)
    {
      switch (cOption)
	{
	case 'I':
	  noTagI=1;
	  break;
	case 'i':
	  iTag=optarg;
	  break;
	}
    }

  bufInput=BufferCreate(100,100);
  bufKey=BufferCreate(100,100);


  if ((BufferGets(bufInput))) createGroupRecord();
  while  ((BufferGets(bufInput)))
    {
      if (testNewRecord())
	{
	  computeFreqCount(currentGroup);
	  /* printf("%s\n", SxmlToString(currentGroup)); */
	  printGroup();
	  SxmlFree(currentGroup);
	  createGroupRecord();
	  continue;
	}
      insertTree(currentList,currentPos);
    }
  computeFreqCount(currentGroup);
  printGroup();
  exit(EXIT_SUCCESS);
}
