#! /usr/bin/env perl 

my $MLLIBS; 
my $VERSION; 
BEGIN {
    $VERSION = "0.1";
    
    # REPLACE THE VALUE OF THIS ASSIGNMENT SO THAT 
    #  $ROOT POINTS TO THE PATH OF PHRECO
    $ROOT = "$ENV{HOME}/local/phreco";
}

use lib "$ROOT/src";
use lib "$ROOT/src/ML";


use strict;

use PHRECO::sentence;
use PHRECO::frclauser;
use PHRECO::config;
use PHRECO::clauseconfig;

use AppConfig qw(:argcount);

my $script = $0;
my $help = << "end_of_help;";
phreco-$VERSION :: fr-clauser
fr-clauser : recognizes clauses in a sentence by filtering and ranking
usage: fr-clauser [options & parameters] 

Modes:   
    -gen     [<dataset>]          Example generation
    -train   <dataset>            Train score functions
    -retrain <dataset>            Retrain score functions
    -label   [<dataset>]          Label dataset, default mode

Training Options:
    -T       <int>                Number of epochs for training. Default: 1.
    -rT -rn                       Starting point for *retraining* mode. 
    -m       <file>               Directory of the model.
    -d       <int>                Degree of polynomial kernel. Default: 1.
    -goldinputs [0|1]             Consider gold(1)/predicted(0) inputs in features, default 1

    -f [reco|good|class]          Feedback type: [reco]gnition, [class]ification, or [good]-updates

Labelling Options:
    -avg                          VP averaged predictions
    -voted                          VP voted predictions
    -last                          VP "last" predictions

    -H       {vp,svm}             Class of learning model.
                                     vp -- voted perceptron
    -T       <int>                Use VP vectors learned until specified epoch
    -se                           Output Start/End predictions along with the clause structure

General Options:
    -v       <int>                Verbosity level. Default: 0.
    -allw                         Consider all words for S and E candidates. 
    -chunkb                       Consider chunk bondary words for S and E candidates. 
    -allSE                        No SE decisions. All candidate words are S/E; ie, no filtering. 
    -goldSE                       No SE decisions. Gold SE points are considered. 

Feature Options:
  Start and End Filtering: 
    -Www     <wspec>              Window of word forms and PoS tags. 
    -Wcw     <wspec>              Window of chunk tags. 

  Scoring : 
    -Sww     <wspec>              Word window at the Start point.  Default: -2:0
    -Eww     <wspec>              Word window at the End point.    Default: 0:2
    -Scw     <wspec>              Chunk window at the Start point. Default: -2:0
    -Ecw     <wspec>              Chunk window at the End point.   Default: -2:0
      <wspec> format : 
           0         : not used
           <l>:<r>   : from word <l> to <r>, relative to central word 0
    -pats     [0|1]               Use patterns. Default: 1.
    -plain    [0|1]               Plain patterns (do not reduce internal clauses). Default: 0.

    -imap     <file>              Input  file for the mapping: forces to work with the 
                                    features whose labels are in the mapping.
    -omap     <file>              Output file for the mapping. 
    -cc  <natural>                Feature count cut-off; default 0; 

end_of_help;




my $speccfg = AppConfig->new({ CASE=>1 }, "model_dir=s");
my $config  = AppConfig->new( { CASE=>1, GLOBAL => { ARGCOUNT => ARGCOUNT_ONE } });

PHRECO::config::config_definition($config);
PHRECO::clauseconfig::config_definition($config);

$config->define("verbose", { ALIAS => "v", DEFAULT => 0 });

if (!@ARGV) {
    print $help; 
    exit; 
}


## Options Processing
#  first the config file
# $speccfg->getopt("pass_through");
# if (defined($speccfg->spec)) {
#     $config->file($speccfg->spec);
# }
# #  then the command-line arguments
# $config->getopt();

$speccfg->getopt("pass_through");
if (defined($speccfg->model_dir) and -f $speccfg->model_dir."/spec") {
    $config->set("model_dir", $speccfg->model_dir);
    $config->file($speccfg->model_dir."/spec");
}
#  then the command-line arguments
$config->getopt();




# Mandatory Arguments 
my $mode = undef

# arguments
my $dsfile = undef;


if ($config->get("gen")) {
    $mode = "g";
    $dsfile = (@ARGV) ? shift @ARGV : undef;
}
if ($config->get("train")) {
    defined($mode) and die "$script : two modes specified (", $mode, " and t)!\n"; 
    $mode = "t";
    if (defined($config->get("training_file"))) {
	$dsfile = $config->get("training_file"); 
    }
    else {
	$dsfile = shift @ARGV or die "$script: unspecified dataset!\n$help";
    }
}
if ($config->get("retrain")) {
    defined($mode) and die "$script : two modes specified (", $mode, " and r)!\n"; 
    $mode = "r";
    $dsfile = shift @ARGV or die "$script: unspecified dataset!\n";
}
if (!defined($mode)) {
    $mode = "l";
    $dsfile = (@ARGV) ? shift @ARGV : undef;    
}

## Input Specification
my $input_spec = undef;
if ($config->get("input")) {
    $input_spec = $config->get("input"); 
}
elsif ($mode eq "l") {
    $input_spec = "wpcs";
}
else {
    $input_spec = "wpcs";
}
PHRECO::sentence::set_input_spec($input_spec);


## Output SE predictions
my $output_se = 0;
if ($config->get("se")) {
    $output_se = 1;
}


my $all_words = $config->get("all_words");
my $chunk_boundaries = $config->get("chunk_boundaries");
my $epochs = $config->get("epochs");
my $verbose = $config->get("verbose");
PHRECO::frclauser::set_verbosity($verbose);


#----------------------------------------------------------------------
#  M A I N   P R O G R A M 
#

my $parser = PHRECO::frclauser->new($mode, $config);

if ($mode eq "t" or $mode eq "r") {
    $parser->train($dsfile, $epochs);
    exit;
}

# else
## Labelling, generation

## Open DataSet
my ($dsfh);
if (defined($dsfile)) {
    if ($dsfile =~ /\.gz$/) {
	open DS, "gunzip -c $dsfile |" or die "$script: error opening dataset $dsfile: $!\n";    
    }
    else {
	open DS, $dsfile or die "$script: error opening dataset $dsfile: $!\n";    
    }
    $dsfh = \*DS;
}
else {
    $dsfh = \*STDIN;
}

my $nsentence = 0;
my $s = PHRECO::sentence->read_from_stream($nsentence, $dsfh);
while ($s) {
    
    my $A = {};
    my $y = $parser->process_sentence($s, $A);
    
    ## Write Split 
    if ($mode eq "l") {
	my ($w, $cl);
	my @W = $s->words;

	my @SEtags = $y->to_SE_tagging($s->length);

	if ($output_se) {
	    foreach $w ( @W ) {
		print join (" ", 
			    $w->field(3), $SEtags[$w->id],
			    exists($A->{S}{$w->id}{"S"}) ? $A->{S}{$w->id}{"S"} : -1, 
			    exists($A->{E}{$w->id}{"S"}) ? $A->{E}{$w->id}{"S"} : -1
			    ), "\n";
		
	    }
	}
	else {
	    foreach $w ( @W ) {
		print join (" ", $w->fields, $SEtags[$w->id]), "\n";
	    }
	}
	print "\n";
    }
    
    $nsentence++;
    $s = PHRECO::sentence->read_from_stream($nsentence, $dsfh);
}


