<commit_before>package Whapps::CatalogAPI;
use 5.014;
use strict;

our $VERSION = 1.0;
our $API_VERSION = 'v1';

use LWP::UserAgent qw();
use URI::Escape qw(uri_escape);
use Encode qw(encode_utf8 is_utf8);
use JSON qw(encode_json decode_json);
use Data::UUID qw();
use Digest::HMAC_SHA1 qw(hmac_sha1);
use MIME::Base64 qw(encode_base64);
use DateTime;
use Carp;

=head1 DESCRIPTION

Whapps::CatalogAPI is a perl interface to the catalogapi.com API.

All of the methods return a perl data structure that looks exactly like the
JSON response examples at catalogapi.com (unless stated otherwise in these docs)
except that the response data structures
do not include the {METHODNAME_response}->{METHODNAME_response} hash keys.
This makes it easier to work with the responses.

=head1 CATALOG BROWSE METHODS

=head2 new

You must pass your secret key and the endpoint uri
when creating a new Whapps::CatalogAPI instance.

    my $api = Whapps::CatalogAPI->new(
        secret_key => 'yoursecretkey',
        endpoint => 'your_domain.dev.catalogapi.com',
        # keep_alive is on by default.
        # Set to 0 if you encounter any issues with keep_alive.
        keep_alive => 1,
        );

=cut

my $AGENT;

sub new
{
    my ($class, %args) = @_;
    my $self = bless \%args, $class;
    
    # will only be used to setup the $AGENT on the first instance creation
    my $keep_alive = 2;
    if (defined($args{keep_alive}) && !$args{keep_alive})
    {
        $keep_alive = 0;
    }
    
    confess "your secret_key is required"
        unless $self->{secret_key};
    $self->{secret_key} =~ s/\s//g;
    
    confess "your endpoint is required"
        unless $self->{endpoint};
    $self->{endpoint} =~ s/^https?:\/\///;
    $self->{endpoint} =~ s/\/.*$//;
    
    unless ($AGENT)
    {
        $AGENT = LWP::UserAgent->new( keep_alive => $keep_alive );
        $AGENT->agent("Whapps::CatalogAPI $VERSION");
        $AGENT->timeout(30);
    }
    
    return $self;
}

=head2 redemption_active

    Returns 1 if redemption is active (i.e. production orders can be placed.)
    Returns 0 if not.

=cut
sub redemption_active
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'redemption_active' );
    return $response->{redemption_active_response}->{redemption_active_result};
}

=head2 list_available_catalogs

    my $list_available_catalogs_response = $api->list_available_catalogs();
    
    my $domain = $list_available_catalogs_response->{domain};
    print "The following sockets are available for the $domain->{account_name} account.";
    
    foreach my $socket (@{ $domain->{sockets}->{Socket} })
    {
        print "got socket: $socket->{socket_name}\n";
    }

=cut
sub list_available_catalogs
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'list_available_catalogs' );
    my $ref = $response->{list_available_catalogs_response}->{list_available_catalogs_result};
    $self->_validate_response($ref->{credentials});
    return $ref;
}

=head2 catalog_breakdown

    my $catalog_breakdown_response = $api->catalog_breakdown(
        socket_id => $socket_id,
        is_flat => 0 );
    
    foreach my $category (@{ $catalog_breakdown_response->{categories}->{Category} })
    {
        process_category($category, 0);
    }
    
    sub process_category
    {
        my ($category, $depth) = @_;
        print "\t"x$depth . "found category: $category->{name}\n";
        
        foreach my $child (@{ $category->{children}->{Category} })
        {
            process_category($child, ++$depth);
        }
    }
    
=cut
sub catalog_breakdown
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'catalog_breakdown', %args );
    my $ref = $response->{catalog_breakdown_response}->{catalog_breakdown_result};
    $self->_validate_response($ref->{credentials});
    return $ref;
}

=head2 search_catalog

Check the catalogapi.com documentation for a full list of search parameters.

    my $search_catalog_response = $api->search_catalog(
        socket_id => $socket_id,
        search => 'ipod' );
    
    foreach my $item (@{ $search_catalog_response->{items}->{CatalogItem} })
    {
        print "found item: $item->{name}\n";
    }

=cut
sub search_catalog
{<commit_msg>adding the method, docs to follow<commit_after>package Whapps::CatalogAPI;
use 5.014;
use strict;

our $VERSION = 1.0;
our $API_VERSION = 'v1';

use LWP::UserAgent qw();
use URI::Escape qw(uri_escape);
use Encode qw(encode_utf8 is_utf8);
use JSON qw(encode_json decode_json);
use Data::UUID qw();
use Digest::HMAC_SHA1 qw(hmac_sha1);
use MIME::Base64 qw(encode_base64);
use DateTime;
use Carp;

=head1 DESCRIPTION

Whapps::CatalogAPI is a perl interface to the catalogapi.com API.

All of the methods return a perl data structure that looks exactly like the
JSON response examples at catalogapi.com (unless stated otherwise in these docs)
except that the response data structures
do not include the {METHODNAME_response}->{METHODNAME_response} hash keys.
This makes it easier to work with the responses.

=head1 CATALOG BROWSE METHODS

=head2 new

You must pass your secret key and the endpoint uri
when creating a new Whapps::CatalogAPI instance.

    my $api = Whapps::CatalogAPI->new(
        secret_key => 'yoursecretkey',
        endpoint => 'your_domain.dev.catalogapi.com',
        # keep_alive is on by default.
        # Set to 0 if you encounter any issues with keep_alive.
        keep_alive => 1,
        );

=cut

my $AGENT;

sub new
{
    my ($class, %args) = @_;
    my $self = bless \%args, $class;
    
    # will only be used to setup the $AGENT on the first instance creation
    my $keep_alive = 2;
    if (defined($args{keep_alive}) && !$args{keep_alive})
    {
        $keep_alive = 0;
    }
    
    confess "your secret_key is required"
        unless $self->{secret_key};
    $self->{secret_key} =~ s/\s//g;
    
    confess "your endpoint is required"
        unless $self->{endpoint};
    $self->{endpoint} =~ s/^https?:\/\///;
    $self->{endpoint} =~ s/\/.*$//;
    
    unless ($AGENT)
    {
        $AGENT = LWP::UserAgent->new( keep_alive => $keep_alive );
        $AGENT->agent("Whapps::CatalogAPI $VERSION");
        $AGENT->timeout(30);
    }
    
    return $self;
}

=head2 redemption_active

    Returns 1 if redemption is active (i.e. production orders can be placed.)
    Returns 0 if not.

=cut
sub redemption_active
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'redemption_active' );
    return $response->{redemption_active_response}->{redemption_active_result};
}

=head2 list_available_catalogs

    my $list_available_catalogs_response = $api->list_available_catalogs();
    
    my $domain = $list_available_catalogs_response->{domain};
    print "The following sockets are available for the $domain->{account_name} account.";
    
    foreach my $socket (@{ $domain->{sockets}->{Socket} })
    {
        print "got socket: $socket->{socket_name}\n";
    }

=cut
sub list_available_catalogs
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'list_available_catalogs' );
    my $ref = $response->{list_available_catalogs_response}->{list_available_catalogs_result};
    $self->_validate_response($ref->{credentials});
    return $ref;
}

=head2 catalog_breakdown

    my $catalog_breakdown_response = $api->catalog_breakdown(
        socket_id => $socket_id,
        is_flat => 0 );
    
    foreach my $category (@{ $catalog_breakdown_response->{categories}->{Category} })
    {
        process_category($category, 0);
    }
    
    sub process_category
    {
        my ($category, $depth) = @_;
        print "\t"x$depth . "found category: $category->{name}\n";
        
        foreach my $child (@{ $category->{children}->{Category} })
        {
            process_category($child, ++$depth);
        }
    }
    
=cut

sub catalog_breakdown
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'catalog_breakdown', %args );
    my $ref = $response->{catalog_breakdown_response}->{catalog_breakdown_result};
    $self->_validate_response($ref->{credentials});
    return $ref;
}

=head2 catalog_marketing

    my $catalog_marketing_response = $api->catalog_marketing(
        socket_id => $socket_id,
        page      => 'shop' );

    TODO add its output/usage

=cut

sub catalog_marketing
{
    my ($self, %args) = @_;
    my $response = $self->_make_get_request( method => 'catalog_marketing', %args );
    my $ref = $response->{catalog_marketing_response}->{catalog_marketing_result};
    $self->_validate_response($ref->{credentials});
    return $ref;
}

=head2 search_catalog

Check the catalogapi.com documentation for a full list of search parameters.

    my $search_catalog_response = $api->search_catalog(
        socket_id => $socket_id,
        search => 'ipod' );
    
    foreach my $item (@{ $search_catalog_response->{items}->{CatalogItem} })
    {
        print "found item: $item->{name}\n";
    }

=cut
sub search_catalog
{
{'fraction_non_alphanumeric': 0.13231580103217305, 'fraction_numerical': 0.007137366860656638, 'mean_word_length': 3.2580645161290325, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 112, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2882709', 'n_tokens_mistral': 3023, 'n_tokens_neox': 2958, 'n_words': 760}