package Pinto::Remote::SelfContained;
# ABSTRACT:  interact with a remote Pinto repository


use v5.10;
use Moo;

use Carp qw(croak);
use Module::Runtime qw(module_notional_filename use_package_optimistically);
use Pinto::Remote::SelfContained::Action;
use Pinto::Remote::SelfContained::Chrome;
use Pinto::Remote::SelfContained::Types qw(Uri);
use Pinto::Remote::SelfContained::Util qw(current_username password_exec);
use Types::Standard qw(Bool InstanceOf Int Maybe Str);

use namespace::clean;

our $VERSION = '1.999'; # TRIAL VERSION

with qw(
    Pinto::Remote::SelfContained::HasHttptiny
);

has root => (
    is      => 'ro',
    isa     => Uri,
    default => sub { $ENV{PINTO_REPOSITORY_ROOT} },
    coerce  => 1,
);

has username => (
    is      => 'ro',
    isa     => Str,
    default => sub { current_username() },
);

has password => (
    is      => 'ro',
    isa     => Maybe[Str],
    default => sub {
        return $ENV{PINTO_PASSWORD} if $ENV{PINTO_PASSWORD};
        return password_exec($ENV{PINTO_PASSEXEC}) if $ENV{PINTO_PASSEXEC};
    },
);

has chrome => (
    is      => 'lazy',
    isa     => InstanceOf['Pinto::Remote::SelfContained::Chrome'],
    builder => sub { Pinto::Remote::SelfContained::Chrome->new },
);


sub run {
    my ($self, $action_name, @args) = @_;

    my $action = $self->make_action($action_name, @args);

    $action->execute;
}

sub make_action {
    my ($self, $action_name, @args) = @_;

    my $action_args = (@args == 1 && ref $args[0] eq 'HASH') ? $args[0] : { @args };

    my $action_class = $self->load_class_for_action(name => $action_name);

    local $SIG{__WARN__} = sub { $self->chrome->warning($_) for @_ };

    my $action = $action_class->new(
        name     => $action_name,
        args     => $action_args,
        root     => $self->root,
        username => $self->username,
        password => $self->password,
        chrome   => $self->chrome,
        httptiny => $self->httptiny,
    );
}

sub run_streaming {
    my ($self, $streaming_callback, $action_name, @args) = @_;

    my $action = $self->make_action($action_name, @args);

    $action->execute($streaming_callback);;
}

sub load_class_for_action {
    my ($self, %args) = @_;

    my $action_name = $args{name}
        or croak('Must specify an action name');

    my $class  = __PACKAGE__ . "::Action::\u$action_name";
    use_package_optimistically($class);
    return $INC{ module_notional_filename($class) } ? $class : __PACKAGE__.'::Action';
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Pinto::Remote::SelfContained - interact with a remote Pinto repository

=head1 VERSION

version 1.999

=head1 DESCRIPTION

Pinto::Remote::SelfContained is a partial clone of L<Pinto::Remote>, but
without the server parts, and therefore a much smaller dependency graph.
Documentation can be found in that module.

This class exists for situations where your organisation is using Pinto, and
doesn't currently have the bandwidth to move away from it to any alternative,
but wants something smaller than the whole of L<Pinto> for interacting with the
remote repo.

=head1 METHODS

=head2 C<< run($action_name => %action_args) >>

Loads the Action subclass for the given C<$action_name> and constructs
an object using the given C<$action_args>.  If the subclass
C<Pinto::Remote::SelfContained::Action::$action_name> does not exist, then it falls
back to the L<Pinto::Remote::SelfContained::Action> base class.

=head1 AUTHOR

Brad Lhotsky <brad@divisionbyzero.net>

=head1 CONTRIBUTOR

=for stopwords Aaron Crane

Aaron Crane <arc@cpan.org>

=for :stopwords cpan testmatrix url bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan

=head1 SUPPORT

=head2 Websites

The following websites have more information about this module, and may be of help to you. As always,
in addition to those websites please use your favorite search engine to discover more resources.

=over 4

=item *

MetaCPAN

A modern, open-source CPAN search engine, useful to view POD in HTML format.

L<https://metacpan.org/release/Pinto-Remote-SelfContained>

=item *

CPAN Testers

The CPAN Testers is a network of smoke testers who run automated tests on uploaded CPAN distributions.

L<http://www.cpantesters.org/distro/P/Pinto-Remote-SelfContained>

=item *

CPAN Testers Matrix

The CPAN Testers Matrix is a website that provides a visual overview of the test results for a distribution on various Perls/platforms.

L<http://matrix.cpantesters.org/?dist=Pinto-Remote-SelfContained>

=back

=head2 Bugs / Feature Requests

This module uses the GitHub Issue Tracker: L<https://github.com/reyjrar/Pinto-Remote-SelfContained/issues>

=head2 Source Code

This module's source code is available by visiting:
L<https://github.com/reyjrar/Pinto-Remote-SelfContained>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2020 by Aaron Crane.

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

=cut
