package Treex::Tool::Parser::JDEPP;
$Treex::Tool::Parser::JDEPP::VERSION = '0.13095';
use strict;
use warnings;

use Moose;
use Treex::Core::Common;
use Treex::Core::Config;
use Treex::Tool::ProcessUtils;
use Treex::Core::Resource;

has model_dir => ( isa => 'Str', is => 'rw', required => 1 );

sub BUILD {
    my ($self) = @_;

    # TODO find architecture independent solution
    my $bin_path = require_file_from_share(
        'installed_tools/parser/jdepp/bin/jdepp',
        ref($self)
    );
 
    #TODO: fix setting up of the model_dir via Treex (see W2A::JA::ParseJDEPP)
    # right now only way of selecting model_dir is via configuring Jdepp
    # my $model_dir = $self->model_dir;

    # in the worst case, it will use default model
    my $cmd = "$bin_path".' 2>/dev/null';
 
    # start JDEPP parser
    my ( $reader, $writer, $pid ) = Treex::Tool::ProcessUtils::bipipe( $cmd, ':encoding(utf-8)' );    

    $self->{reader} = $reader;
    $self->{writer} = $writer;
    $self->{pid}    = $pid;

    return;
}

sub parse_sentence {

    my ( $self, $forms_rf, $tags_rf ) = @_;

    if ( ref($forms_rf) ne "ARRAY" or ref($tags_rf) ne "ARRAY" ) {
        log_fatal('Both arguments must be array references.');
    }

    if ( $#{$forms_rf} != $#{$tags_rf} or @$forms_rf == 0 ) {
        log_warn "FORMS: @$forms_rf\n";
        log_warn "TAGS:  @$tags_rf\n";
        log_fatal('Both arguments must be references to nonempty arrays of equal length.');
    }

    if ( my @ret = grep { $_ =~ /^\s+$/ } ( @{$forms_rf}, @{$tags_rf} ) ) {
        log_debug("@ret");
        log_fatal('Elements of argument arrays must not be empty and must not contain white-space characters');
    }

    my @parents;
    my $input = "";
    my $writer = $self->{writer};
    my $reader = $self->{reader};

    foreach my $form ( @$forms_rf ) {
        my $tag = shift @$tags_rf;
        $tag =~ s{-}{,}g;
        $input .= $form . "\t" . $tag . "\n";
    }
    $input .= "EOS\n";  

    print $writer $input;

    my $line = <$reader>;
    
 
    #JDEPP uses different token ordering than Treex, because it creates "bunsetsus" out of multiple tokens (parsing is done on these "bunsetsus"
    my @bun_heads;
    my $current_token = 1;
    while ( $line !~ "EOS") {

        log_fatal("Unitialized line (perhaps JDEPP was not initialized correctly).") if (!defined $line);        

        $line = <$reader>;
        #log_info($_);
        next if $line =~ /^#|EOS/;
        if ( $line =~ /^\*/ ) {
            $line =~ s{^\*\s+}{};    
            (my $bun, my $parent) = split / /, $line;
            $bun_heads[ $bun ] = $current_token;
            $parent =~ s{D\n}{};
            $parents[ $current_token - 1 ] = $parent
        }
        else {
            if ( !defined $parents[ $current_token - 1 ] ) { $parents[ $current_token - 1 ] = -2; }
            $current_token += 1;
        }
    } 

    $current_token = 1;
    my $i = 0;
    while ( defined $parents[ $i ] ) {
        if ( $parents[ $i ] >= 0 ) {
            my $parent = $bun_heads[ $parents[ $i ] ];
            $parents[ $i ] = $parent;
            $current_token = $i + 1;
        } else {
            if ( $parents[ $i ] == -2 ) { $parents[ $i ] = $current_token; }
            else { 
                $parents[ $i ] = 0;
                $current_token = $i + 1;
            }
        }
        $i += 1;   
    }
    
    return \@parents;

}

# ----------------- cleaning up ------------------
# TODO : cleanup

1;

__END__

=pod

=encoding utf-8

=head1 NAME

Treex::Tool::Parser::JDEPP - perl wrapper for C implemented japanese dependency parser JDEPP

=head1 VERSION

version 0.13095

=head1 SYNOPSIS

 use Treex::Tool::Parser::JDEPP;
 my $model_dir; # default 'data/models/parser/jdepp/kyoto-partial'
 my $parser = Treex::Tool::Parser::JDEPP->new( model_dir => $model_dir );
 my @tokens = qw(わたし は 日本語 を 話し ます);
 my @tags = qw(名詞-代名詞-一般-* 助詞-係助詞-*-* 名詞-一般-*-* 助詞-格助詞-一般
-* 動詞-自立-*-* 助動詞-*-*-*); # IPADIC tagset
 my $parents_rf = $parser->parse_sentence( \@tokens, \@tags );

=head1 DESCRIPTION

This is a Perl wrapper for JDEPP Parser implemented in C.
This parser works with tokens and POS tags generated by MeCab tagger for dependency parsing. Tokens are grouped together into "bunstetsu", then parsing is performed on these bunsetsu. Simple dependencies between each tokens are generated later in this module.

=head1 INSTALLATION

Before installing JDEPP, make sure you have properly installed the Treex-Core package (see L<Treex Installation|http://ufal.mff.cuni.cz/treex/install.html>), since it is prerequisite for this module anyway.
After installing Treex-Core you can install JDEPP using this L<Makefile|https://svn.ms.mff.cuni.cz/svn/tectomt_devel/trunk/install/tool_installation/JDEPP/Makefile> (username "public" passwd "public"). Prior to runing the makefile, you must set the enviromental variable "$TMT_ROOT" to the location of your .treex directory.

You can also install MeCab manually but then you must link the installation directory to the ${TMT_ROOT}/share/installed_tools/parser/jdepp/ (location within Treex share), otherwise the modules will not be able to use the program.

=head1 METHODS

=over

=item $parents_rf = $parser->parse_sentence( \@tokens, \@tags );

Returns reference to the list of parent nodes for input tokens.

=back

=head1 KNOWN ISSUES

So far, JDEPP program could not be succesfully compiled on i686 architecture. If someone will be able to solve this, please send me an e-mail.

=head1 SEE ALSO

L<JDEPP Home Page|http://www.tkl.iis.u-tokyo.ac.jp/~ynaga/jdepp/> more info on JDEPP parser

=head1 AUTHOR

Dušan Variš <dvaris@seznam.cz>

=head1 COPYRIGHT AND LICENSE

Copyright © 2014 by Institute of Formal and Applied Linguistics, Charles University in Prague

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

=cut
