package VCI::Abstract::History;
use Moose;
use MooseX::Method;
use VCI::Util;

# XXX Will also need some sort of graph view of commits for things like Git
#     and Hg.

has 'commits' => (is => 'ro', isa => 'ArrayOfCommits', required => 1);
has 'project' => (is => 'ro', isa => 'VCI::Abstract::Project', required => 1);

method 'union' => named (
    histories => { isa => 'ArrayOfHistories', required => 1 },
    project   => { isa => 'VCI::Abstract::Project', required => 1 },
) => sub {
    my $class = shift;
    my $params = shift;
    my $histories = $params->{histories};
    
    my %commits;
    foreach my $history (@$histories) {
        foreach my $commit (@{ $history->commits }) {
            $commits{$commit->revision} = $commit;
        }
    }
    
    my @result = sort { $a->time <=> $b->time } (values %commits);
    
    return $class->new(commits => \@result, project => $params->{project});
};

__PACKAGE__->meta->make_immutable;

1;

__END__

=head1 NAME

VCI::Abstract::History - The history of a Project, File, Directory, etc.

=head1 DESCRIPTION

Essentially, this represents all of the commits to a particular file,
project, directory, or anything that can be committed.

=head1 METHODS

=head2 Constructors

In addition to C<new>, we implement the following constructor(s):

=over

=item C<union>

=over

=item B<Description>

Given a list of History objects, returns an object that is a union of all
of them. (This is useful for implementing
L<VCI::Abstract::FileContainer/contents_history>.)

=item B<Parameters>

Takes the following named parameters, both of which are required:

=over

=item C<histories>

An arrayref of C<VCI::Abstract::History> objects.

=item C<project>

The L<VCI::Abstract::Project> that the resulting History should be associated
with.

=back

=item B<Returns>

A C<VCI::Abstract::History> that has a union of all the commits in all of
the supplied histories.

=back

=back

=head2 Accessors

All accessors are read-only.

=over

=item C<commits>

An L<ArrayOfCommits|VCI::Util/ArrayOfCommits> that represents a series of
commits to some particular item. It will always be in time order--earliest
commits will be first, more recent commits will be last.

Note that depending on how the History was generated, and depending on the
version-control system in use, what is listed in each commit may or may not
represent the whole commit. That is, if this is the History of a File, each
Commit might only contain information about that particular File, and not
other Files or Directories that were committed at that time.

The most complete History possible will be generated by
L<VCI::Abstract::Project/history>.

=item C<project>

What L<Project|VCI::Abstract::Project> this History came from.

=back

=head1 CLASS METHODS

=head2 Constructors

Usually you won't construct an instance of this class directly, but
instead, ask for this History of a L<Project|VCI::Abstract::Project> or
L<Committable|VCI::Abstract::Committable>.

=over

=item C<new>

Takes all L</Accessors> of this class as named parameters. The following
fields are B<required>: L</commits> and L</project>.

=back
