package VCI::VCS::Svn::Project;
use Moose;
use MooseX::Method;

use Path::Abstract::Underload;
use SVN::Core;

use VCI::VCS::Svn::Commit;
use VCI::VCS::Svn::Directory;
use VCI::VCS::Svn::History;

# Class::MOP 0.75 has a bug in its XS module that makes get_commit_prototype
# below invisible unless we do this explicitly.
use VCI::Abstract::Project;

extends 'VCI::Abstract::Project';

sub BUILD {
    my $self = shift;
    $self->_name_never_ends_with_slash();
    $self->_name_never_starts_with_slash();
}

method 'get_commit' => named (VCI::Abstract::Project::get_commit_prototype()) =>
sub {
    my $self = shift;
    my $params = shift;

    # MooseX::Method always has a hash key for each parameter, even if they
    # weren't passed by the caller.
    delete $params->{$_} foreach (grep { !defined $params->{$_} } keys %$params);
    
    # We only use our custom implementation if the History object
    # doesn't already exist, and if we were just asked for a revision id.
    if (!defined $self->{history} && defined $params->{revision}
        && keys(%$params) == 1)
    {
        my $commits = $self->_x_get_commits(
            start => $params->{revision}, end => $params->{revision},
            limit => 1);
        return $commits->[0];
    }
    
    unshift(@_, $params);
    return $self->SUPER::get_commit(@_);
};

# We need a dirent for the root directory, so we have to override the
# default build_root_directory.
sub _build_root_directory {
    my $self = shift;
    # XXX Probably should use x_ra.
    my $ctx = $self->repository->vci->x_client;
    my $info;
    # Getting the root_directory of the root_project only works if there's
    # no slash on the end of the URL.
    my $name = $self->name eq '' ? '' : ('/' . $self->name);
    $ctx->info($self->repository->x_root_noslash . $name, undef,
               'HEAD', sub { $info = $_[1] }, 0);
    return VCI::VCS::Svn::Directory->new(
        path => '', project => $self, x_info => $info);
}

sub _build_history {
    my $self = shift;
    my $commits = $self->_x_get_commits();
    return VCI::VCS::Svn::History->new(commits => $commits, project => $self);
}

method '_x_get_commits' => named (
    start => { isa => 'Int', default => 0 },
    end   => { isa => 'Int' },
    limit => { isa => 'Int', default => 0 },
    path  => { isa => 'Str' },
) => sub {
    my ($self, $params) = @_;
    my $ra = $self->repository->x_ra;
    $params->{path} ||= $self->name;
    $params->{end}  ||= $ra->get_latest_revnum;

    my @commits;
    $ra->get_log([$params->{path}], $params->{start}, $params->{end},
                                   # discover_changed_paths, strict_node_history
                 $params->{limit}, 1, 0,
                 sub { push(@commits, VCI::VCS::Svn::Commit->x_from_log($self, @_)) });
    return \@commits;
};

__PACKAGE__->meta->make_immutable;

1;
