package Pcore::API::Moz v0.3.0;

use Pcore -dist, -class;
use Pcore::API::Response;
use Digest::HMAC_SHA1 qw[];    ## no critic qw[Modules::ProhibitEvilModules]

has api_id      => ( is => 'ro', isa => Str,         required => 1 );
has api_key     => ( is => 'ro', isa => Str,         required => 1 );
has api_expires => ( is => 'ro', isa => PositiveInt, default  => 172_800 );    # 2 days

has _threads => ( is => 'ro', isa => PositiveOrZeroInt, default => 0, init_arg => undef );
has _pool => ( is => 'ro', isa => ArrayRef, default => sub { [] }, init_arg => undef );

sub check ( $self, $cb = undef ) {
    my $blocking_cv = defined wantarray ? AE::cv : undef;

    $self->url_metrics(
        ['google.com'],
        103079215104,
        sub ($res) {
            if ($blocking_cv) {
                $blocking_cv->send($res);
            }
            else {
                $cb->($res) if $cb;
            }

            return;
        }
    );

    return $blocking_cv ? $blocking_cv->recv : ();
}

# NOTE 10 domains max. allowed
sub url_metrics ( $self, $domains, $metric, $cb ) {
    die q[Max. 10 domains are allowed per search] if $domains->@* > 10;

    if ( $self->{_threads} > 0 ) {
        push $self->{_pool}->@*, [ $domains, $metric, $cb ];

        return;
    }

    $self->{_threads}++;

    my $url_params = {
        AccessID => $self->api_id,
        Expires  => time + $self->api_expires,
        Cols     => $metric,
    };

    $url_params->{Signature} = P->data->to_b64( Digest::HMAC_SHA1::hmac_sha1( $url_params->{AccessID} . $LF . $url_params->{Expires}, $self->api_key ) );

    my $url = 'https://lsapi.seomoz.com/linkscape/url-metrics/?' . P->data->to_uri($url_params);

    P->http->post(
        $url,
        timeout   => 180,
        body      => P->data->to_json($domains),
        on_finish => sub ($res) {
            my $api_res;

            if ( $res->status != 200 ) {
                $api_res = Pcore::API::Response->new( { status => $res->status, reason => $res->reason } );
            }
            else {
                my $json = eval { P->data->from_json( $res->body->$* ); };

                if ($@) {
                    $api_res = Pcore::API::Response->new( { status => 999, reason => 'Invalid JSON body' } );
                }
                else {
                    $api_res = Pcore::API::Response->new( { status => 200 } );

                    for my $i ( 0 .. $domains->$#* ) {
                        $api_res->{result}->{ $domains->[$i] } = $json->[$i];
                    }
                }
            }

            $self->{_threads}--;

            if ( my $next_call = shift $self->{_pool}->@* ) {
                $self->url_metrics( $next_call->@* );
            }

            $cb->($api_res);

            return;
        },
    );

    return;
}

1;
## -----SOURCE FILTER LOG BEGIN-----
##
## PerlCritic profile "pcore-script" policy violations:
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
## | Sev. | Lines                | Policy                                                                                                         |
## |======+======================+================================================================================================================|
## |    2 | 19                   | ValuesAndExpressions::RequireNumberSeparators - Long number not separated with underscores                     |
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
##
## -----SOURCE FILTER LOG END-----
__END__
=pod

=encoding utf8

=head1 NAME

Pcore::API::Moz

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 ATTRIBUTES

=head1 METHODS

=head1 SEE ALSO

=head1 AUTHOR

zdm <zdm@softvisio.net>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by zdm.

=cut
