=head1 NAME

iPE::AnnotationPlugin::GTFPlugin - The GTF plugin subclass of the iPE::AnnotationPlugin.  Uses Evan Keibler's GTF.pm.

=head1 DESCRIPTION

See iPE::AnnotationPlugin for information.

=cut

package iPE::AnnotationPlugin::GTFPlugin;

use iPE;
use iPE::Globals;
use iPE::Options;
use iPE::Annotation::Transcript;
use GTF;

use strict;

use base ("iPE::AnnotationPlugin");

sub gtf { shift->{GTF_} }

sub populate {
    my ($this, $length) = @_;

    # All this code is elminated because it is not a reliable way to check
    # the validity of a transcript.  It only emits up to 4 errors of the same
    # type before giving up.  I might look for a better way to do this later.

    my $g = new iPE::Globals();

    # The bad_list aref contains the error codes which should be put on the 
    # warning_fh list.  These genes are thrown away.
    my $bad_list = [];
    if($g->options->annotationSanityCheck) {
        $bad_list->[15] = 1; # no CDS in transcript
        $bad_list->[16] = 1; # wrong start codon len
        $bad_list->[18] = 1; # wrong stop codon len
        $bad_list->[21] = 1; # CDS before start
        $bad_list->[22] = 1; # CDS after stop
        $bad_list->[33] = 1; # bad loc of start codon (overlaps cds)
        $bad_list->[34] = 1; # bad loc of stop codon (overlaps cds)
        $bad_list->[35] = 1; # start codon length wrong
        $bad_list->[36] = 1; # stop codon length wrong
        $bad_list->[38] = 1; # start is greater than stop
        $bad_list->[41] = 1; # bad length of transcript
        $bad_list->[45] = 1; # overlapping cds feature in tx
        $bad_list->[46] = 1; # stop codon in terminal cds
        $bad_list->[47] = 1; # start codon in intron region
        $bad_list->[48] = 1; # transcript contains 0 length introns
    }

    #check to see if we're allowing partial transcripts.  throw out
    #this transcript if we are not.

    # as of now there is no implemented way to handle partial transcripts
    # so it might be wise at this point to always throw them out, 
    # but it should also be documented.
    if ($g->options->allowPartialTranscripts == 0) {
        $bad_list->[17] = 1;  #no start codon
        $bad_list->[19] = 1;  #no stop codon
    }
    my $warnfile_name = "/tmp/iPE_gtf_warnings".time;
    open (WARN, "+>".$warnfile_name)
        or die __PACKAGE__.
            ":could not open temporary warnings file $warnfile_name\n";
    $this->{GTF_} = GTF::new({ gtf_filename => $this->filename,
                               fix_gtf      => 1,
                               bad_list     => $bad_list,
                               warning_fh   => \*WARN});
    seek WARN, 0, 0;
    chomp(my @lines = <WARN>);
    my $warn_string = join("\"", @lines);
    $warn_string =~ s/.*Bad Genes://;
    close WARN;
    unlink $warnfile_name 
        or warn __PACKAGE__.":could not delete file $warnfile_name.\n";

    my @txs = @{$this->gtf->transcripts};
    my @inter_feats = (@{$this->gtf->inter}, @{$this->gtf->inter_cns});
    $this->{GTF_} = undef; # reduce memory usage.
    for my $inter_feat (@inter_feats) {
        push @txs, $inter_feat->transcript;
    }
    for my $tx 
        (sort { $a->start <=> $b->start || $a->stop <=> $b->stop } @txs) {
        #throw away the transcript if we got a warning on it
        if($warn_string =~ m"@{[$tx->id]}") {
            Warn(__PACKAGE__.
               ": discarding transcript ".$tx->id." because of warnings\n");
            next;
        }

        #iterate over the features which were concerned with.
        my $iTx = new iPE::Annotation::Transcript($tx->id, $tx->gene->id);
        msg ($iTx->id."\n");
        for my $featArr ($tx->utr5, $tx->utr3, $tx->cds, $tx->exons, 
                $tx->inter, $tx->inter_cns) {
            my $features = $featArr;
            my $num_features = scalar(@$features);
            my $cur_features = 0;

            for my $f (@$features) {
                $f->output_gtf($g->dbg_fh()) if($g->options->debugOutput);
                my ($start, $stop, $startFrame, $endFrame);
                for my $fm (@{$this->featureMap->featureMappings}) {
                    $start = $f->start-1;
                    $stop = $f->stop-1;
                    if($f->strand eq '-') {
                        $startFrame = -1;
                        $endFrame = $f->frame;
                        $endFrame = 0 if($endFrame eq ".");
                    }
                    else {
                        $startFrame = $f->frame;
                        $startFrame = 0 if($startFrame eq ".");
                        $endFrame = -1;
                    }
                    $fm->addToTranscript(
                        $iTx,
                        $f->type,
                        $f->start-1, $f->stop-1,
                        $startFrame, $endFrame,
                        $f->strand,
                        $cur_features,
                        $num_features,
                        $length);
                }
                $cur_features++;
            }
        }
        #$iTx->finalize($length, $tx->id, $tx->gene->id);
        push @{$this->{transcripts_}}, $iTx;
    }
}

sub suppliesGeneID { 1; }

=head1 SEE ALSO

L<iPE::AnnotationPlugin>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu)

=cut

1;
