// Training of client Speakers
// The same than TrainTarget but train simultaneoulsy 1 model for each cluster (set of segments with the same label)
// found in the input files labels.
// One option in order to save the n models as a modification of the world model - save disk space
 int TrainTargetByLabel(Config& config)
{
  String inputClientListFileName = config.getParam("targetIdList");
  String inputWorldFilename = config.getParam("inputWorldFilename");
  String outputSERVERFilename = config.getParam("mixtureServer");
  // label for selected frames - Only the frames associated with this label, in the label files, will be used
  //bool fixedLabelSelectedFrame;
  bool initByClient=false;
  bool aprioriWorld=true;
  if (config.existsParam("initByClient")) initByClient=true;
  if (config.existsParam("aprioriClient")){
    aprioriWorld=false;
    initByClient=true;
  }
  bool saveCompleteServer=false;
  bool outputAdaptParam=false;
  if (config.existsParam("outputAdaptParam")) outputAdaptParam=config.getParam("outputAdaptParam").toBool();
  
  try{
    XList inputClientList(inputClientListFileName,config);          // read the Id + filenames for each client
    XLine *linep;
    inputClientList.getLine(0);
    MixtureServer ms(config);
    StatServer ss(config, ms);
    if (verbose) cout << "TrainTarget - by label opption - Load world model [" << inputWorldFilename<<"]"<<endl;
    MixtureGD& world = ms.loadMixtureGD(inputWorldFilename);
    // *********** Target loop ***************** 
    while ((linep=inputClientList.getLine()) != NULL){             // linep gives the XLine with the Id of a given client and the list of files
      String clientId=(*linep->getElement());                      // Get the Client ID (clientId)
      XLine featureFileListp=linep->getElements();	           // Get the list of feature file for the client (end of the line)
      FeatureServer fs(config,featureFileListp);                   // Reading the features (from several files)
      if (verbose) cout << "Train label models for client ["<<clientId<<"]"<<endl;   
      MixtureGD &clientGModel=ms.createMixtureGD();
      if (initByClient) {
          if (verbose) cout << "Load client model [" << clientId <<"]"<<endl;
          clientGModel = ms.loadMixtureGD(clientId); //not necessary to load client model
      }
      SegServer segmentsServer;                                                             // Create the segment server for managing the segments/clusters
      LabelServer labelServer;                                                              // Create the lable server, for indexing the segments/clusters
      initializeClusters(featureFileListp,segmentsServer,labelServer,config);               // Reading the segmentation files for each feature input file
      verifyClusterFile(segmentsServer,fs,config);                                          // Verify if the segments ending before the end of the feature files...
      for (unsigned long codeSelectedFrame=0;codeSelectedFrame<segmentsServer.getClusterCount();codeSelectedFrame++){ // For each cluster
	String clientIdByLabel=clientId+"_"+labelServer.getLabel(codeSelectedFrame).getString(); // Build the model name for the client and the label
	if (verbose) cout << "Train labeldependent model ["<<clientIdByLabel<<"]"<<endl;   
	SegCluster& selectedSegments=segmentsServer.getCluster(codeSelectedFrame);          // Gives the cluster of the selected/used segments
	MixtureGD & clientMixture = ms.duplicateMixture(world,DUPL_DISTRIB);       // Creating clientMixture as a copy of the world model
	ms.setMixtureId(clientMixture,clientIdByLabel);                                     // Set the client model Id
	if (initByClient)                                                                   // During trainig data statistic estimation by EM,
	  clientMixture=clientGModel;                                                       // the global client model is used for initalization
	if (aprioriWorld)                                                                   // EM algo with MAP criterion
	  adaptModel(config,ss,ms,fs,selectedSegments,world,clientMixture);          // A priori info is the world model  
	else adaptModel(config,ss,ms,fs,selectedSegments,clientGModel,clientMixture);// A priori info is the client model-by default initByClient is also set
        if (!outputAdaptParam) {
            if (verbose) cout << "Save client model ["<<clientIdByLabel<<"]" << endl;
            clientMixture.save(clientIdByLabel, config);                                           // Save the client model
        }
	if (!saveCompleteServer){
	  long tid=ms.getMixtureIndex(clientIdByLabel);      // TO BE SUPPRESSED BY
	  ms.deleteMixtures(tid,tid);            // ADDING a delete on a mixture pointor
	  ms.deleteUnusedDistribs();
	  }
      }      
      if (!saveCompleteServer){
	long tid=ms.getMixtureIndex(clientId);      // TO BE SUPPRESSED BY
	ms.deleteMixtures(tid,tid);                 // ADDING a delete on a mixture pointor
	ms.deleteUnusedDistribs();
      }                                                                   // end of the the label loop fr a speaker
    } // end of the the target loop 
    
    // Save the complete mixture server
    // TODO
  } // fin try
  

  
  catch (Exception& e)
    { 
      cout << e.toString().c_str() << endl;
    }
  return 0;
}
void launchTurnDetectionProcess(Config & config){

	String outputFilesPath=config.getParam("outputFilesPath");

	String inputListFileName = config.getParam("listFileToSegment");	//file including the list of files to segment
	XLine classToAnalyse;	//Array of labels to analyze
	classToAnalyse.reset();

	if(verbose){
		cout << "*********** Current Configuration ***************" << endl;
		for(unsigned long i=0; i<config.getParamCount(); i++){
			cout << config.getParamName(i) << " => " <<  config.getParamContent(i) << endl;
		}
		cout << "*************************************************" << endl;
	}

	try{
		XList listLabel;
		XList listFileName;
		try{
			listFileName.load(inputListFileName,config);
		}
		catch(FileNotFoundException& e){
			cout<<"There is no files to segment !"<<endl;
		      	exit(-1);
		}
		listFileName.rewind();
		XLine *filep;
		while ((filep=listFileName.getLine()) != NULL){							// For each stream of audio data (in several files in the same line)
			const XLine & listFile=filep->getElements();						// One or several files, as several part of the same stream
		      	MixtureServer ms(config);
	      		StatServer ss(config, ms);
		      	SegServer Resultat;
	      		FeatureServer fs(config,listFile);							// Reading the features (one or more files) 
		      	SegServer segmentsServer;								// Create the segment server for managing the segments/clusters
	      		LabelServer labelServer;								// Create the lable server, for indexing the segments/clusters
		      	initializeClusters(listFile,segmentsServer,labelServer,config);				// Reading the segmentation files for each feature input file
	      		verifyClusterFile(segmentsServer,fs,config);						// Verify if the segments ending before the end of the feature files
			String fileInit=listFile.getElement(0);
			config.setParam("fileSize", String::valueOf(fs.getFeatureCountOfASource(fileInit)));	

			if(config.existsParam("fileRefPath")){
				// assumption: all the segments in the segment server come from the same source file !!!
				displayAllSegmentsFromRef(config, fileInit, fs.getFeatureCountOfASource(fileInit));
			}

			for(unsigned long icluster=0;icluster<segmentsServer.getClusterCount();icluster++){	// for each cluster
				SegCluster& cluster=segmentsServer.getCluster(icluster);
  				SegServer segOutputServer;
  				TurnDetection(config,cluster,segOutputServer,ss,fs,ms,labelServer);
				displayAllSegments(config,segOutputServer); 
  				for(unsigned long i=0;i<segOutputServer.getSegCount();i++){
    					Seg& segment=segOutputServer.getSeg(i);
	    				Resultat.createSeg(segment.begin(),segment.length(),segment.labelCode(),segment.string(),segment.sourceName());
	  			}
			}//for icluster
			saveSegmentation(config,Resultat,fs,outputFilesPath,1);
		}// while
	} // end try
	catch (Exception& e){ 
		cout << e.toString().c_str() << endl;
	}
}//launchTurnDetectionProcess