// main genere automatiquement par xsl
// ne pas modifier
// derniere mise a jour : VF le 29/10/2002 -- derniere version
// inclusions expat
#include <stdio.h>
#include "expat.h"
// inclusions c++
#include <string>
#include "config.h"
#include <map>
using namespace std;
#include <iostream.h>
#include "toi.h"
#include "toiprocessor.h"
#include "toimanager.h"
#include "toisegment.h"
#include "sophyainit.h"
#include <stdexcept>
#ifndef MAXINT
#define MAXINT 2147483647
#endif
	
#include ""
// classe de gestion des balises en design patern object call-back
class ToiPipe
{
public:
  ToiPipe(void);
  virtual ~ToiPipe();
  static void startElement(void *userData, const char *name, const char **atts);
  static void endElement(void *userData, const char *name);
private:
  // pour concordances instances - nom
  map<string,TOIProcessor*> toiProc;
  string id; 
  // gestionnaire de TOI
  TOIManager* mgr;
  void startElementC(const char *name, const char **atts);
  void endElementC(const char *name);
};
ToiPipe::ToiPipe()
{
 // Ouverture du gestionnaire de TOI.
 mgr = TOIManager::getManager();
 // initialisation du processeur courant
 id="";
}
ToiPipe::~ToiPipe()
{
}
void ToiPipe::startElement(void *userData, const char *name, const char **atts)
{
  ToiPipe *toiPipe = (ToiPipe*) userData;
  toiPipe->startElementC(name, atts);
}
void ToiPipe::endElement(void *userData, const char *name)
{
  ToiPipe* toiPipe = (ToiPipe*) userData;
  toiPipe->endElementC(name);
}
void ToiPipe::startElementC(const char *name, const char **atts)
{
  int i;
  //puts(name);
  // filtrage des balises
  if ((string)name == "connect") {
    // mise en ordre des arguments
    string nom;
    TOIProcessor* procin=NULL;
    TOIProcessor* procout=NULL;
    string input;
    string output;
    int taille = 1024;
    bool writeflag = false;
    for (i=0; atts[i]; i+=2) {
      if ((string)atts[i] == "name") {
	nom=atts[i+1];
      }
      if ((string)atts[i] == "procin") {
	map<string,TOIProcessor*>::iterator j=toiProc.find(atts[i+1]);
	if (j != toiProc.end()) { 
	  procin = (*j).second;
	} else {
	   throw ParmError("Connect error: processor in not found");
	}
      }
      if ((string)atts[i] == "procout") {
	map<string,TOIProcessor*>::iterator j=toiProc.find(atts[i+1]);
	if (j != toiProc.end()) {
	  procout = (*j).second;
	} else {
	   throw ParmError("Connect error: processor out not found");
	}
      }
      if ((string)atts[i] == "input") {
	input = atts[i+1];
      }
      if ((string)atts[i] == "output") {
	output = atts[i+1];
      }
    }    
    // connection automatique des toiprocesseurs    
    if (procin != NULL && procout != NULL ) {
      cout << "connect " << output << " " << input << endl;
      mgr->connect(*procout, output, *procin, input, nom, taille, writeflag);
       cout << "connect done" << endl;
    }
  } else if ((string)name == "constraint") {                                // si balise de contrainte     
    TOIProcessor* proc=NULL;
    int min=0;
    int max=MAXINT;
    for (i=0; atts[i]; i+=2) {
      if ((string)atts[i] =="proc") {
        map<string,TOIProcessor*>::iterator j=toiProc.find(atts[i+1]);
	if (j != toiProc.end()) { 
	  proc = (*j).second;
	} else {
	  throw ParmError("Constraint error: processor not found");
	}
      }
      if ((string)atts[i] == "min") {
        min = atoi(atts[i+1]);
      }
      if ((string)atts[i] == "max") {
        max = atoi(atts[i+1]);
      } 
    }
    cout << "setting " << proc << " " << min << " " << max << endl;
    proc->setRequestedSample(min, max);
    cout << "constraint done" << endl;
  
  } else if ((string)name == "start") {                                     // si balise de demarrage 
    cout << "***** Starting execution *****" << endl;
    mgr->startAll();
    // Gestion de la re-connection des threads
    cout<<"***** Joining threads *****"<<endl;
    mgr->joinAll();
    cout<<"***** End threads *****"<<endl; 
    // destruction du toimanager et des processeurs a implementer dans toimanager pour l'utilisation de plusieurs start
    //TOIManager::~toimanager();
    //toiProc.clear();
  
  } else if (id == "") {                                            // si nouveau processeur
  if ((string)name == "") {
    
     ;
    
    
    
    
    , 
    
    
	
    // gestion des arguments du constructeur
    for (i=0; atts[i]; i+=2) {
      // var pour instanciation
        if ((string)atts[i] == "id") {
            id=atts[i+1];
      	}
	
	//initialisation des arguments par defaut si existants
	
	   
	   
	   
	   
	   
	   
	     
	   
	    = ;
	   
	   
	    = "";
	   
	   
	
	// mise a jour des arguments
	
	if ((string)atts[i] == "") {
	   
	   
	   
	    
	    = atoi(atts[i+1]);
	    
	   
	    = atof(atts[i+1]);
	   
	   
	    = atts[i+1];
	     
	}
    	
      }
   
    // creation du toiprocesseur
    toiProc[id] = new  ();
  }
  
  } else {                                           // sinon c une methode
    // gestion des methodes 
  if (id == "") {
    
    
    
    
    if ((string)name == "") {
    
     ;
    
    
    
    
    , 
    
    
	
    // gestion des arguments de la methode
    for (i=0; atts[i]; i+=2) {     
	//initialisation des arguments par defaut si existants
	
	   
	   
	   
	   
	   
	   
	   
	   
	    = ;
	   
	   
	    = "";
	   
	   
	
	// mise a jour des arguments
	
	if ((string)atts[i] == "") {
	   
	   
	   
	   
	    = atoi(atts[i+1]);
	    
	   
	    = atof(atts[i+1]);
	   
	   
	    = atts[i+1];
	   
	}
    	
      }
   
    // appelle de la methode du processeur concerne
    ((*)toiProc[id])-> (); 
    }
    
  }
  
  }
  
}
void ToiPipe::endElementC(const char *name)
{
  // verification si une balise processeur est fermee pour la gestion des methodes d'initialisation
  
  if ((string)name == "") {
    id="";
  }
  
  // execution du pipeline
  if ((string)name == "toipipe") { 
    cout << "***** Starting execution *****" << endl;
    mgr->startAll();
    // Gestion de la re-connection des threads
    cout<<"***** Joining threads *****"<<endl;
    mgr->joinAll();
    cout<<"***** End threads *****"<<endl; 
  }
}
int main(int argc, char *argv[])
{
  char buf[BUFSIZ];
  XML_Parser parser = XML_ParserCreate(NULL);
  int done;
  FILE* fich=fopen(argv[1],"r");
  ToiPipe* toiPipe = new ToiPipe();
  
  // Initialisation de Sophya
  SophyaInit();
  cout << "-- Application start --" << endl;
  XML_SetUserData(parser, toiPipe);
  XML_SetElementHandler(parser, ToiPipe::startElement, ToiPipe::endElement);
  if (fich != NULL) {
    cout << "-- Reading file --" << endl;
    // traitement des balises
    do {
      try {
	size_t len = fread(buf, 1, sizeof(buf), fich);
	done = len < sizeof(buf);
	if (!XML_Parse(parser, buf, len, done)) {
	  fprintf(stderr,
	      "%s at line %d\n",
              XML_ErrorString(XML_GetErrorCode(parser)),
              XML_GetCurrentLineNumber(parser));
	  return 1;
	}
      } catch (PThrowable & exc) {    // Sophya exceptions
	cout << "\ntstdemopipe: Catched Exception \n" << (string)typeid(exc).name() 
	<< " - Msg= " << exc.Msg() << endl;
      } catch (const std::exception & sex) {    // Standard exceptions
	cout << "\ntstdemopipe: Catched std::exception \n" 
      << (string)typeid(sex).name() << endl; 
      } catch (...) {    // Other exceptions
	cout << "\ntstdemopipe: some other exception was caught ! " << endl;
      }
    } while (!done);
    XML_ParserFree(parser);
    fclose(fich);
  } else {
     fprintf(stderr,"file not found");
     return 1;
  }
  return(0);
}