/**********************************************************************
*
*  module   : Hfd
*  fichier  : DamHfdIter.c
*  Auteur   : Jacques DUCLOY
*  Date     : Fevrier 94
*  $Id: DamHfdIter.c,v 1.3 2005/06/22 12:46:16 parmentf Exp $
*
***********************************************************************
* 
*     Copyright (C) 1995 CRIN - CNRS & INRIA Lorraine
*
***********************************************************************/

#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>

#include "StrDict.h"
#include "Hfd.h"

HfdIterator *HfdIteratorCreate(char mode)
{
  HfdIterator *iter;
  iter=(HfdIterator *) malloc(sizeof(HfdIterator));
  iter->table=StrDictCreate(100,100);
  iter->filePathLenght=0;
  iter->subDir=NULL;
  iter->isMultiGroup=0;
  iter->hcs=NULL;
  iter->filePath=NULL;
  iter->mode=mode;
  return iter;
}

void HfdIteratorFree(HfdIterator *iter)
{
  if(iter->isMultiGroup)BufferFree(iter->multiBegin);
  StrDictFreeKey(iter->table);
  if(iter->hcs)SxmlFree (iter->hcs);
  if(iter->filePath)free(iter->filePath);
  if(iter->subDir)HfdIteratorFree(iter->subDir);
  free(iter);
}

HfdIterator *HfdIteratorInit(HfdIterator *hfdIter, char *dirName)
{
  DIR *dir;
  struct dirent *entry;
  char *entryName;
  int l;
  int lmax;

  lmax=0;

  
  StrDictReset (hfdIter->table);
  hfdIter->currentDir=dirName;
  hfdIter->isMultiGroup=0;
  if (strcmp((dirName+strlen(dirName)-4),".hfd")==0)
    {
      char *fName;
      char *type;
      fName=strdup(dirName);
      fName[strlen(dirName)-1]='s';
      fName[strlen(dirName)-2]='c';
      hfdIter->hcs=SxmlFromFile(fName);
      if((type=SxmlGetAttribute(hfdIter->hcs,"type"))
	 &&(strcmp(type,"group")==0)
	 )
	{
	  hfdIter->isMultiGroup=1;
	  hfdIter->multiBegin=BufferCreate(10,10);
	}
    }
  dir = opendir(dirName);

/*
 construction d'une table triee des fichiers constituant un niveau de HFD
 */

  while ((entry=readdir(dir)))
    {
      l=strlen(entry->d_name);
      entryName=malloc(l+1);
      strcpy(entryName,entry->d_name);
      if (l>lmax) lmax=l;
      if (HfdNameIsDir(entryName))
	StrDictAddNewDatum(hfdIter->table,entryName,"D");
      else 
	{
	  if (HfdNameIsFile(entryName))
	    StrDictAddNewDatum(hfdIter->table,entryName,"F");
	  else free(entryName);
        }
    };

  closedir(dir);
  
  lmax+=strlen(dirName)+1+1;
  if(hfdIter->filePathLenght<lmax)
    {
      if(hfdIter->filePathLenght)free (hfdIter->filePath);
      hfdIter->filePath=malloc(lmax);
      hfdIter->filePathLenght=lmax;
    }
  StrDictIteratorReset(hfdIter->table);
  hfdIter->subDirExploring=0;

  return hfdIter;
}

char *HfdNextFilePath(HfdIterator *hfdIter)
{
  char *nameFile;
  char *typeFile;
  if (hfdIter->subDirExploring)
    {
      if((nameFile=HfdNextFilePath(hfdIter->subDir)))
	return nameFile;
      else hfdIter->subDirExploring=0;
    }
  nameFile=StrDictNext(hfdIter->table);
  if (nameFile)
    {
      typeFile=StrDictValue(hfdIter->table);
      strcpy(hfdIter->filePath,hfdIter->currentDir);
      strcat(hfdIter->filePath,"/");
      strcat(hfdIter->filePath,nameFile);
      if (hfdIter->isMultiGroup)
	{
	  BufferStrcpy(hfdIter->multiBegin,nameFile);
	  BufferTailCut(hfdIter->multiBegin,3);
	}
      if (typeFile[0]=='F') return hfdIter->filePath;
      if (!hfdIter->subDir)hfdIter->subDir=HfdIteratorCreate(hfdIter->mode);
      hfdIter->subDirExploring=1;
      HfdIteratorInit(hfdIter->subDir, hfdIter->filePath);
      return HfdNextFilePath(hfdIter->subDir);
    }
  else return NULL;
}


/***************************  HfdStreamIterator ******************************/

HfdStreamIterator *HfdStreamIteratorCreate(char mode)
/* 
                h : hfd
                a : all
                x : xml     
 */
{
  HfdStreamIterator *iter;
  iter = (HfdStreamIterator *) malloc(sizeof(HfdStreamIterator));
  iter->listEntry=NULL;
  iter->hfdExploring=0;
  iter->indicEntry=0;
  iter->stdinHasBeenReaded=0;
  iter->oneStreamHasBeenReaded=0;
  iter->listIsClosed=0;
  iter->hfdIterator=HfdIteratorCreate(mode);
  iter->currentFilePath=NULL;
  iter->mode=mode;
  return iter;
}

HfdStreamIterator *HfdStreamIteratorSetStreams(HfdStreamIterator *iter, char **listName)
{
  iter->listEntry=listName;
  return iter;
}

FILE* HfdNextStream(HfdStreamIterator *iter)
{
  char *currentStream;
  if(iter->listIsClosed)return NULL;
  if(iter->oneStreamHasBeenReaded)fclose(iter->currentFile);
  if(iter->hfdExploring)
    {
      if((iter->currentHfdPath=HfdNextFilePath(iter->hfdIterator)))
	{
	  iter->currentFile=fopen(iter->currentHfdPath,"r");
	  return (iter->currentFile);
	}
      else iter->hfdExploring=0;
    }
  if((currentStream=iter->listEntry[iter->indicEntry++]))
    {
      iter->oneStreamHasBeenReaded=1;
      if (strcmp(currentStream,"-")==0)
	{
	  if(iter->stdinHasBeenReaded)return NULL;
	  iter->stdinHasBeenReaded=1;
	  iter->currentFile=stdin;
	}
      else
	{
	  static Buffer* bPath=NULL;
	  char *cleanStream;
	  if ((currentStream[strlen(currentStream)-1])=='/')
	    {
	      if(!bPath)bPath=BufferFromString(currentStream);
	      else BufferStrcpy(bPath, currentStream);
	      BufferTailCut(bPath,1);
	      cleanStream=BufferString(bPath);
	    }
	  else cleanStream=currentStream;

	  if(HfdNameIsDir(cleanStream))
	    {
	      iter->hfdExploring=1;
	      HfdIteratorInit(iter->hfdIterator,cleanStream);
	      iter->currentHfdPath=HfdNextFilePath(iter->hfdIterator);
	      iter->currentFile=fopen(iter->currentHfdPath,"r");
	    }
	  else
	    {
	      if (iter->currentFilePath)free (iter->currentFilePath);
	      iter->currentFilePath=strdup(cleanStream);
	      iter->currentFile=fopen(cleanStream,"r");
	    }
	}
    }
  else
    {
      iter->listIsClosed=1;
      if(iter->stdinHasBeenReaded)return NULL;
      if(iter->oneStreamHasBeenReaded)return NULL;
      iter->stdinHasBeenReaded=1;
      iter->currentFile=stdin;
    }
  return (iter->currentFile);
}

char *HfdStreamIteratorCurrentFileName(HfdStreamIterator *iter)
{
  return iter->currentFilePath;
}
