=head1 NAME

iPE::SequenceReader::NoLoad::FASTA - NoLoad version of the SequenceReader format.

=head1 DESCRIPTION

This SequenceReader expects a file formatted with a fasta header.  It should also have equal line length for each line, and only a single sequence in the file. 

=head1 FUNCTIONS

=over 8

=cut
package iPE::SequenceReader::NoLoad::FASTA;

use Carp;
use iPE::Util::DNATools;
use base ("iPE::SequenceReader::NoLoad");
use strict;

=item new (memberHash)

Constructs a new FASTA sequence reader.  This doesn't read in the sequences, it simply make calculations which will enable it to later read portions of the sequence in from the file.

=cut
sub new {
    my $class = shift;
    my $this = $class->SUPER::new(@_);

    $this->{seqName_} = $this->{header_};
    my $fh = $this->fh;
    my $header = <$fh>;
    $this->{lineLength_} = length(<$fh>) - 1;
    
    while(<$fh>) { $this->{length_} += length ($_) - 1; }
    $this->{length_} += $this->{lineLength_};

    seek $fh, 0, 0;
    
    return $this;
}

=item length ()

Returns length of the sequence.

=cut
sub length      { shift->{length_}          }
#internal--length of each line (which is equivalent to length+1 for the newline)
sub lineLength  { shift->{lineLength_}      }
=item seqName ()

seqName is the name of the sequence as given in in the fasta header.

=cut
sub seqName    { shift->{seqName_}        }

=item getSeq (start, length), getRevSeq (start, length)

This gets sequence directly from the file.  This works similarly to substr in that it takes in a start and 'offset' or length of the substring to retrieve.  Note that getRevSeq also reverse-complements the sequence.

=cut
sub getSeq {
    my ($this, $start, $length) = @_;

    #add one for each newline character it will have to skip over.
    my $startOfs = $this->{headerLength_}+$start+ 
        int($start/$this->{lineLength_});
    my $readLength = $length + int(($start+$length-1)/$this->{lineLength_}) - 
        int($start/$this->{lineLength_});

    my $fh = $this->{fh_};
    my $seq;
    sysseek($fh, $startOfs, 0);
    sysread($fh, $seq,      $readLength);
    $seq = uc($seq);

    $seq =~ s/\n//g;
    
    return $seq;
}

sub getRevSeq {
    my ($this, $start, $length, $seqNum) = @_;
    
    $start = $this->length-$start-$length;
    my $forwSeq = $this->getSeq($start, $length, $seqNum);
    my $revSeqRef = reverseComplement(\$forwSeq);
    return $$revSeqRef;
}

=back

=head1 SEE ALSO

L<iPE::SequenceReader::NoLoad>

=head1 AUTHOR

Bob Zimmermann (rpz@cse.wustl.edu).
(With much acknowledgement to Sam Gross's code).

=cut
1;
