package Acme::Insult::Glax 1.0 {    # https://www.freepublicapis.com/insult-api
    use v5.38;
    use HTTP::Tiny;
    use JSON::Tiny qw[decode_json];
    use URI;
    use parent 'Exporter';
    our %EXPORT_TAGS = ( all => [ our @EXPORT_OK = qw[insult adjective] ] );
    #
    use overload '""' => sub ( $s, $u, $b ) { $s->{insult} // () };
    my $api = URI->new('https://insult.mattbas.org/api/');
    #
    sub _http ( $endpoint, %params ) {
        state $http
            //= HTTP::Tiny->new( default_headers => { Accept => 'application/json' }, agent => sprintf '%s/%.2f ', __PACKAGE__, our $VERSION );
        ( my $hey = $api->clone )->path( '/api/' . $endpoint . '.json' );
        $hey->query_form(%params);
        my $res = $http->get( $hey->as_string );    # {success} is true even when advice is not found but we'll at least know when we have valid JSON
        $res->{success} ? decode_json( $res->{content} ) : ();
    }
    #
    sub insult (%args) { my $ref = _http( insult => %args ); $ref ? bless $ref, __PACKAGE__ : $ref }

    sub adjective ( $lang //= 'en' ) {
        my $ref = _http( adjective => ( lang => $lang ) );
        $ref ? bless $ref, __PACKAGE__ : $ref;
    }
}
1;
__END__

=encoding utf-8

=head1 NAME

Acme::Insult::Glax - Programmatically Generate Insults

=head1 SYNOPSIS

    use Acme::Insult::Glax qw[insult];
    say insult( );

=head1 DESCRIPTION

Acme::Insult::Glax provides 'insulting' statements generated by the RESTful libInsult API.

=head1 METHODS

These functions may be imported by name or with the C<:all> tag.

=head2 C<insult( [...] )>

Tear someone down.

    my $shade = insult( ); # Random insult
    print insult( lang => 'en_corporate', who => 'John and Eric', plural => 1 );
    print insult( lang => 'en_corporate', who => 'John' );
    print insult( lang => 'en_corporate', who => 'John' );

You may request specific insults by passing parameters.

Expected parameters include:

=over

=item C<lang>

Insult's language style. Expected styles include:

=over

=item C<en>

Plain English. This is the default.

=item C<en_corporate>

English with corporate jargon inserted. Perfect for the 4:50p work email.

=back

=item C<template>

Insult template.

The default value is different depending on the parameters passed to the API:

=over

=item C<lang =E<gt> 'en'>

    You are as <adjective> as <article target=adj1> <adjective min=1 max=3 id=adj1> <amount> of <adjective min=1 max=3> <animal> <animal_part>

=item C<lang =E<gt> 'en', who =E<gt> 'Alex'>

    Alex is as <adjective> as <article target=adj1> <adjective min=1 max=3 id=adj1> <amount> of <adjective min=1 max=3> <animal> <animal_part>

=item C<lang =E<gt> 'en', plural =E<gt> 1>

    You are as <adjective> as <article target=adj1> <adjective min=1 max=3 id=adj1> <amount> of <adjective min=1 max=3> <animal> <animal_part>

=item C<en_corporate>

    We <adverb> <verb> <adjective min=1 max=3> <noun>

=item C<lang =E<gt> 'en_corporate', who =E<gt> 'Alex'>

    Alex <adverb> <verb id=verb><verb_3rd target=verb> <adjective min=1 max=3> <noun>

=item C<lang =E<gt> 'en_corporate', plural =E<gt> 1>

    We <adverb> <verb> <adjective min=1 max=3> <noun>"

=back

A few examples might be...

    John and Eric <adverb> <verb id=verb><verb_3rd target=verb> <adjective min=1 max=3> <noun>
    # John and Eric proactively facilitates cutting-edge elastic products

    John and Eric are as <adjective> as <article target=adj1> <adjective min=1 max=3 id=adj1> <amount> of <adjective min=1 max=3> <animal> <animal_part>
    # John and Eric is as disgusting as an unsatisfactory mass of stinky revolting boring maggot toes

These are undocumented but from my tinkering, I've figured out that templates can accept the following pseudo-XML tags:

=over

=item C<E<lt>articleE<gt>>

Properly fills in a/an depending on what follows it.

You may target another field by its id.

    ... <article target='adj1' /> <adjective id='adj1' max='3' /> ...

=item C<E<lt>adverbE<gt>>

=item C<E<lt>adjectiveE<gt>>

    <adjective min=1 max=3 id=adj1>

=item C<E<lt>amountE<gt>>

=item C<E<lt>animalE<gt>>

=item C<E<lt>animal_partE<gt>>

=item C<E<lt>nounE<gt>>

=item C<E<lt>verbE<gt>>

Inserts an action or activity.

=back

Be aware that some of these are unsupported when the language is set to C<en_corporate>.

=item C<who>

Person to insult. If present, changes the template to third person singular.

=item C<plural>

If present (along with a C<who> value), changes the template to third person plural.

=back

=head2 C<adjective( [...] )>

    my $adjective0 = adjective( );
    my $adjective1 = adjective( 'en' );
    my $adjective2 = adjective( 'en_corporate' );

Generates a single descriptive adjective in plain text.

Expected parameters include:

=over

=item C<lang>

Language style. Expected values include:

=over

=item C<en>

Plain English. This is the default.

=item C<en_corporate>

English with corporate jargon inserted.

=back

=back

=head1 LICENSE & LEGAL

Copyright (C) Sanko Robinson.

This library is free software; you can redistribute it and/or modify it under the terms found in the Artistic License
2. Other copyrights, terms, and conditions may apply to data transmitted through this module.

Insults are generated by L<libInsult|https://gitlab.com/mattia.basaglia/LibInsult> which is maintained by L<Mattia
"Glax" Basaglia|https://mattbas.org/>.

=head1 AUTHOR

Sanko Robinson E<lt>sanko@cpan.orgE<gt>

=head2 ...but why?

I'm inflicting this upon the world because L<oodler577|https://github.com/oodler577/> invited me to help expand Perl's
coverage of smaller open APIs. Blame them or L<join us|https://github.com/oodler577/FreePublicPerlAPIs> in the effort.

=cut
