#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#
#  (C) Paul Evans, 2020 -- leonerd@leonerd.org.uk

package Metrics::Any::Adapter;

use 5.010;  # //
use strict;
use warnings;

our $VERSION = '0.04';

=head1 NAME

C<Metrics::Any::Adapter> - set the C<Metrics::Any> adapter for the program

=head1 SYNOPSIS

In a program or top-level program-like module:

   use Metrics::Any::Adapter 'Prometheus';

=head1 DESCRIPTION

The C<use> statement which loads this module sets the adapter module for
L<Metrics::Any> to report metrics generated by an modules the program uses.

The first value passed should be a string giving the name of an adapter
module, which will be expected under the C<Metrics::Any::Adapter::>-prefix.
This module will be loaded and set as the adapter to use. Any additional
arguments will be passed to the constructor of the adapter instance.

   use Metrics::Any::Adapter Custom => "another arg";

   # implies
   $adapter = Metrics::Any::Adapter::Custom->new( "another arg" );

=head1 ENVIRONMENT

=head2 METRICS_ANY_ADAPTER

I<Since version 0.04.>

Sets the default adapter type to use if the program has not otherwise
requested one.

Normally this is set to C<Null>, which loads L<Metrics::Any::Adapter::Null>.
By overriding this to a different value, a default adapter can be loaded
without modifying the program. This may be useful for example, when running
unit tests:

   $ METRICS_ANY_ADAPTER=Stderr ./Build test

Additional arguments can be specified, separated by commas or equals signs.

   $ METRICS_ANY_ADAPTER=File,path=metrics.log ./program.pl

Note that if a program requests a specific adapter that will override this
variable.

=cut

sub import
{
   my $pkg = shift;
   my $caller = caller;
   $pkg->import_into( $caller, @_ );
}

my $adaptertype = "Null";
my @adapterargs;
if( my $val = $ENV{METRICS_ANY_ADAPTER} ) {
   ( $adaptertype, @adapterargs ) = split m/[,=]/, $val;
}

sub import_into
{
   my ( $pkg, $caller, @args ) = @_;

   ( $adaptertype, @adapterargs ) = @args if @args;
}

my $adapter;

sub adapter
{
   shift;

   return $adapter //= do {
      my $class = "Metrics::Any::Adapter::$adaptertype";
      unless( $class->can( 'new' ) ) {
         ( my $file = "$class.pm" ) =~ s{::}{/}g;
         require $file;
      }
      $class->new( @adapterargs );
   };
}

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;
