package Bio::Mitomaster;

use Moose;
use Bio::Mitomaster::SpeciesRef;
with 'Bio::Mitomaster::SeqManipRole';


=head1 NAME

Bio::Mitomaster - Tool for mitochondrial DNA.

=cut


our $VERSION = '0.10';


=head1 SYNOPSIS

Do you have mitochondrial DNA data that you want to analyze?  Is there an established reference sequence for the species to which your data is derived?  If you answered yes to both of these questions then Bio::Mitomaster might be for you.


 use Bio::Mitomaster;

 my $mm = Bio::Mitomaster->new(species=>'human', reference=>'rCRS');
 my $seq = $mm->seq(file=>'my_file_name.fasta');
 my $variants = $seq->variants();  # seqs are automatically aligned and variants extracted

 # print a list of the variants in the sequence
 for (keys %{$variants}){
    print "$_  $variants->{$_}\n"
 }


Read the Bio::Mitomaster::Manual (perldoc Bio::Mitomaster::Manual) for a guide to using this framework.  Each package also contains its own documentation, but read the manual first. 

=cut



=head1 ATTRIBUTES

Mitomaster objects have an encapsulated Bio::Mitomaster::SpeciesRef object that provides access to all the meta-data for the species.  Methods provided by that class that are accessible through Mitomaster objects include: species, reference, codon_code, locus, protein, transcript, and translation.

=cut


# Would have liked to have delegated species and reference to the SpeciesRef
# object since it also contains those attributes, but encountered deep
# recursion errors during object construction. 
has 'species' => (#FOLDBEG
    is => 'ro',
    isa => 'Str',
    default => 'human',
    required => 1,
);#FOLDEND
 
has 'reference' => (#FOLDBEG
    is => 'ro',
    isa => 'Str',
    default => 'rCRS',
    required => 1,
);#FOLDEND


# An internal reference object used to retrieve meta data.
has 'species_ref' => (#FOLDBEG
    is => 'ro',
    isa => 'Bio::Mitomaster::SpeciesRef',
    lazy_build => 1,
    handles =>{
        codon_code => 'codon_code',
        end => 'end',
        locus => 'locus',
        protein => 'protein',
        ref_seq => 'ref_seq',
        start => 'start',
        transcript => 'transcript',
        translation => 'translation',
        wrapping => 'dna_wrapping',
    },
);#FOLDEND



sub _build_species_ref {#FOLDBEG
    my $self = shift;

    my $r = Bio::Mitomaster::SpeciesRef->new(species=>$self->species, 
        reference=>$self->reference);

    unless (ref $r) {
        confess $r;
    }

    return $r;
}#FOLDEND


=head1 METHODS


=head2 new()

=head2 new(species=>'human', reference=>'rCRS')

The constructor for new Mitomaster objects.  This is a class method, so call it with Bio::Mitomaster->new().  All Mitomaster objects have a species and a reference, which if not specified default to 'human' and 'rCRS'.



=head2 species_list

Retreives a list of the current reference data.  Call this as a class method: 

 Bio::Mitomaster->species_list;

and you will find out which species and references are available in the software for analysis.

=cut

sub species_list {#FOLDBEG
# This should be modified once the reference data is stored in YAML files.  The
# output should be generated by analyzing the available species and reference
# sequences.  Make a nicely formatted string value and send it back in a
# return statement so that the user can get the list by calling this as a
# class method.

    return "human, rCRS\n";

}#FOLDEND



=head2 seq(file=>'my_file')

=head2 seq(variants=>{1=>'A', 3=>'C'})

=head2 seq(file=>'my_file' start=>577 end=>16023)


The constructor for a new DNA Seq object. The list of variants can also be in a file.  See Bio::Mitomaster::Manual for a description of the .poly file format and a list of supported seq file formats.

The start and end values will be set automatically if not declared, but it is generally a good idea to explicitly declare them.  If the alignment program detects that a sequence read is shorter than was declared, an error is triggered.  This might help prevent analyzing partial sequences that are believed to be full ones.  On the other hand, the start and end boundaries can be used to read part of a full sequence.  In fact, the software always reads the full sequence, but the start and end boundaries will be checked each time any part of the sequence is presented back to the user and trimmed accordingly.  The ref_seq method will do likewise.  Remember that start and end are read only attributes, so to look at a different region of a sequence you have to create a new one with different start and end values.


=cut

sub seq {#FOLDBEG
    eval {require Bio::Mitomaster::Seq};

    my $self = shift;
    my %args = @_;
     
    my $variants;
    if ($args{file}){

        # Decide the type of sequence file and what module will handle it
        my $io;
        if ($args{file} =~ /\.fas/) {
            eval { require Bio::Mitomaster::FastaIO };
            $io = Bio::Mitomaster::FastaIO->new;
        }
        elsif ($args{file} =~ /\.gen|\.gb/) {
            eval { require Bio::Mitomaster::GenbankIO };
            $io = Bio::Mitomaster::GenbankIO->new;
        }
        elsif ($args{file} =~ /\.var/) {
            eval { require Bio::Mitomaster::VariantsIO };
            $io = Bio::Mitomaster::VariantsIO->new;
        }

        # Read the sequence file(s) and generate seq strings
        my @seq_strings = $io->read_seqs($args{file});

        # Check our calling context to make sure the user knew how many
        # Seq objects to expect and return them.  Do this here to save
        # the expense of doing alignments and creating objects if the 
        # user only expected to get one Seq object.

        if ( (@seq_strings > 1) && !wantarray ) {
            confess "There is more than one sequence in file: ", $args{file}, 
                " but you called seq in scalar context";
        }


        # Align each of the seq strings to get a list of variants and
        # instantiate the Seq objects.
        eval {require Bio::Mitomaster::Alignment};





        #eval {require Bio::Mitomaster::FileXXXX};
        #my $io = Bio::Mitomaster::FileXXXX->new
        #my $seq_string = $io->read_file(file=>$args{file});


        #Unless the file is of type .poly
        #eval {require Bio::Mitomaster::Alignment};
        #my $alignment = Bio::Mitomaster::Alignment->new($seq_string);


        # Do some checking of the start and end values

        #if ($args{start} and $args{start} < $alignment->{start}) {
        #    confess "Seq start: ", $alignment->{start}, " is less than declared start: ", $args{start};
        #}
        #$args{start} = $alignment->{start};

        #if ($args{end} and $args{end} > $alignment->{end}) {
        #    confess "Seq end: ", $alignment->{end}, " is less than declared end: ", $args{end};
        #}
        #$args{end} = $alignment->{end};


    }
    elsif ($args{variants}){
        # Variants were passed explicitly.  Life is easy.  We may want to add some checking
        # here to see that only legitimate values (positions and variants) were passed.
        $variants = $args{variants};

        $args{start} = 1 unless $args{start};
        $args{end} = length($self->ref_seq) unless $args{end};

    }
    else {
        confess "seq method requires either a 'file' or 'variants' argument";
    }


    return Bio::Mitomaster::Seq->new(species_ref=>$self->species_ref, 
        start=>$args{start}, end=>$args{end}, variants=>$variants);

}#FOLDEND




=head1 AUTHOR

Marty Brandon, C<< <marty.brandon at gmail.com> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-bio-mitomaster-mitoseq at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Bio-Mitomaster-MitoSeq>.  I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Bio::Mitomaster


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Bio-Mitomaster-MitoSeq>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Bio-Mitomaster-MitoSeq>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/Bio-Mitomaster-MitoSeq>

=item * Search CPAN

L<http://search.cpan.org/dist/Bio-Mitomaster-MitoSeq/>

=back


=head1 ACKNOWLEDGEMENTS


=head1 COPYRIGHT & LICENSE

Copyright 2009 Marty Brandon, all rights reserved.

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


=cut

no Moose;
__PACKAGE__->meta->make_immutable();
1; # End of Bio::Mitomaster
