#!/usr/bin/perl
use strict; 
use utf8;
use XML::XPath;
use warnings;
     
# Définition globale des encodage d'entrée et de sortie du script à utf8
binmode STDIN,  ':encoding(utf8)'; #indiquer que l'entree est en utf8
binmode STDOUT, ':encoding(utf8)'; #indiquer que la sortie est en utf8
     
# On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script. Dans notre cas c'est bao3_rb_demo.pl)
if($#ARGV!=1){print "usage : perl $0 dossier_BAO2 fichier_motif";exit;} #$#ARGV indique le dernier indice (nombre d'element moins 1)
     
# Enregistrement des arguments de la ligne de commande dans les variables idoines
my $dossier= shift @ARGV; #prendre les arguments de la ligne de commande et les stocker dans une variable. Stocker le nom du fichier dans $file
my $patterns_file = shift @ARGV; #stocker le fichier motif dans $patterns_file

# création d'un dossier de sorties
my $sortie="BAO3/";

if (! -e $sortie){	
	mkdir($sortie) or die ("Problème à la création du répertoire : $!");
}

opendir(DIR, $dossier) or die "Erreur d'ouverture de repertoire: $!\n";
my @files = readdir(DIR);
closedir(DIR);

foreach my $file(@files){
	if ($file=~/([^\/\.]+?)_tagged\.xml$/){
		# récupération du nom de rubrique
		my $rub=$1;
		
		# Ouverture du fichiers de motifs
		open(PATTERNSFILE, $patterns_file) or die "can't open $patterns_file: $!\n"; 
		
		# lecture du fichier contenant les motifs, un motif par ligne (par exemple : NOM ADJ)
		while (my $ligne = <PATTERNSFILE>) { #lire le fichier du motif et a chaque ligne extraire les patrons
			# Appel à  la procédure d'extraction des motifs
			&extract_pattern($file,$ligne,$rub);
		}
		 
		# Fermeture du fichiers de motifs
		close(PATTERNSFILE);
	}
}
    # routine de construction des chemins XPath
    sub construit_XPath{
        # On récupère la ligne du motif recherché
        my $local_ligne=shift @_;
       
        # initialisation du chemin XPath
        my $search_path=""; 
       
        # on supprime avec la fonction chomp un éventuel retour à la ligne
        chomp($local_ligne); #enlever les retours a la ligne
       
        # on élimine un éveltuel retour chariot hérité de windows
        $local_ligne=~ s/\r$//;
       
        # Construction au moyen de la fonction split d'un tableau dont chaque élément a pour valeur un élément du motif recherché
        my @tokens=split(/ /,$local_ligne); #separer les patterns par un espace
       
        # On commence ici la construction du chemin XPath
        # Ce chemin correspond au premier noeud "element" de l'arbre XML qui répond au motif cherché
        $search_path="//element[contains(data[\@type=\"type\"],\"$tokens[0]\")]"; #chercher un element qui contient parmi ses fils data un attribut type (despecialiser le @ et type).
       
        # Initialisation du compteur pour la boucle de construction du chemin XPath
        my $i=1; #puisqu'on a plusieurs elements dans notre motif on fait une boucle pour affiner la requete Xpath
        while ($i < $#tokens) {
            $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"$tokens[$i]\")]"; #concatener les conditions pour que "element" satisfasse toutes les conditions
            $i++;
        }
        my $search_path_suffix="]";
       
        # on utilise l'opérateur x qui permet de répéter la chaine de caractère à sa gauche autant de fois que l'entier à sa droite,
        # soit $i fois $search_path_suffix
        $search_path_suffix=$search_path_suffix x $i; #calculer le nombre de crochets ouverts
       
        # le chemin XPath final
        $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"".$tokens[$#tokens]."\")]"
                                    .$search_path_suffix; #rajouter au chemin les crochets qui manquent
            # print  "$search_path\n";
     
        # on renvoie à la procédure appelant le chemin XPath et le tableau des éléments du motif
        return ($search_path,@tokens);
    }
     
    # routine d'extraction du motif
    sub extract_pattern{ 
		my $file=shift;
        # On récupère la ligne du motif recherché
        my $ext_pat_ligne= shift @_; #@_: tableau des arguments passes a la procedure
		my $rub=shift;
        # Appel de la fonction construit_XPath pour le motif lu à la ligne courrante du fichier de motif
        my ($search_path,@tokens) = &construit_XPath($ext_pat_ligne,$rub); #construire le chemin Xpath pour trouver dans le bon "element"
       
        # définition du nom du fichier de résultats pour le motif en utilisant la fonction join
        my $match_file = $sortie.$rub."-extract-".join('_', @tokens).".txt"; #join sur un tableau colle les uns aux autres avec un "_"

        # Ouverture du fichier de résultats encodé en UTF-8
        open(MATCHFILE,">:encoding(UTF-8)", "$match_file") or die "can't open $match_file: $!\n"; #pas necessaire le enconding
       
        # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML
        my $xp = XML::XPath->new( filename => $dossier."/".$file ) or die "big trouble"; #construire une classe
       
        # Parcours des noeuds du ficher XML correspondant au motif, au moyen de la méthode findnodes
        # qui prend pour argument le chemin XPath construit précédement
        # avec la fonction "construit_XPath"
        foreach my $noeud ( $xp->findnodes($search_path)) { #chercher les "elements" qui satisfont le chemin construit en haut
            # Initialisation du chemin XPath relatif du noeud "data" contenant
            # la forme correspondant au premier élément du motif
            # Ce chemin est relatif au premier noeud "element" du bloc retourné
            # et pointe sur le troisième noeud "data" fils du noeud "element"
            # en l'identifiant par la valeur "string" de son attribut "type"
            my $form_xpath="";
            $form_xpath="./data[\@type=\"string\"]"; #chercher le troisieme fils data (chercher le fils data dont l'attribut type est string)
           
            # Initialisation du compteur pour la boucle d'éxtraction des formes correspondants
            # aux éléments suivants du motif
            my $following=0;
     
            # Recherche du noeud data contenant la forme correspondant au premier élément du motif     
            # au moyen de la fonction "find" qui prend pour arguments:
            #           1. le chemin XPath relatif du noeud "data"
            #           2. le noeud en cours de traitement dans cette boucle foreach
            # la fonction "find" retourne par défaut une liste de noeuds, dans notre cas cette liste
            # ne contient qu'un seul élément que nous récupérons avec la fonction "get_node"
            # enfin nous en imprimons le contenu textuel au moyen de la méthode string_value
            print MATCHFILE $xp->find($form_xpath,$noeud)->get_node(1)->string_value," "; #ecrire dans le fichier 
           
            # Boucle d'éxtraction des formes correspondants aux éléments suivants du motif
            # On descend dans chaque noeud element du bloc
            while ( $following < $#tokens) {
                # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
                $following++;
               
                # Construction du chemin XPath relatif du noeud "data" contenant
                # la forme correspondant à l'élément suivant du motif
                # Notez bien l'utilisation du compteur $following tant dans la condition de la boucle ci-dessus
                # que dans la construction du chemin relatif XPath
                my $following_elmt="following-sibling::element[".$following."]"; #calculer le chemin qui va se trouver dans le troisieme fils data           
                $form_xpath=$following_elmt."/data[\@type=\"string\"]"; #concatenation
     
                #  Impression du contenu textuel du noeud data contenant la forme correspondant à l'élément suivant du motif
                print MATCHFILE $xp->find($form_xpath,$noeud)->get_node(1)->string_value," ";
           
                # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
                # $following++;
            }
            print MATCHFILE "\n"; #rajouter un retour a ligne pour que les motifs de correspondance soit separes par un retour a la ligne 
        }
        # Fermeture du fichiers de motifs
        close(MATCHFILE);
    }