#!/usr/bin/perl -w
# vi: set ts=2 sw=2 noai ic showmode showmatch:

#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
#    02110-1301, USA

package Finance::Quote::CurrencyRates::UniRate;

use strict;
use warnings;

use constant DEBUG => $ENV{DEBUG};
use if DEBUG, 'Smart::Comments';

use JSON;

our $VERSION = '1.70_01'; # TRIAL VERSION

sub parameters {
  return ('API_KEY');
}

sub new
{
  my $self = shift;
  my $class = ref($self) || $self;

  my $this = {};
  bless $this, $class;

  my $args = shift;

  ### UniRate->new args : $args

  # UniRate supports an environment variable for the API key for parity
  # with the Twelvedata and FinanceAPI currency-rate modules. An explicit
  # API_KEY in $args overrides the environment variable.
  $this->{API_KEY} = $ENV{'UNIRATEAPI_API_KEY'};
  $this->{API_KEY} = $args->{API_KEY} if (ref $args eq 'HASH') and (exists $args->{API_KEY});

  return $this;
}

sub multipliers
{
  my ($this, $ua, $from, $to) = @_;

  my $url = 'https://api.unirateapi.com/api/rates'
      . '?from=' . ${from}
      . '&to=' . ${to}
      . '&api_key=' . $this->{API_KEY};

  my $reply = $ua->get($url,
      'Accept'     => 'application/json',
      'User-Agent' => 'finance-quote-unirate/0.01');

  return unless ($reply->code == 200);

  my $body = $reply->content;

  ### HTTP body: $body

  my $json_data = eval { JSON::decode_json $body };
  return if $@ or !$json_data;

  return unless exists $json_data->{'rate'};

  my $rate = $json_data->{'rate'};

  ### Rate from JSON: $rate

  return unless $rate + 0;

  # For small rates, request the inverse.
  if ($rate < 0.001) {
    ### Rate is too small, requesting inverse : $rate
    my ($a, $b) = $this->multipliers($ua, $to, $from);
    return ($b, $a);
  }

  return (1.0, $rate);
}


1;

__END__

=head1 NAME

Finance::Quote::CurrencyRates::UniRate - Obtain currency rates from
https://unirateapi.com

=head1 SYNOPSIS

    use Finance::Quote;

    $q = Finance::Quote->new(currency_rates => {order    => ['UniRate'],
                                                unirate  => {API_KEY => ...}});

    $value = $q->currency('18.99 EUR', 'USD');

=head1 DESCRIPTION

This module fetches currency rates from https://unirateapi.com and provides
data to Finance::Quote to convert the first argument to the equivalent value
in the currency indicated by the second argument.

UniRate covers 1000+ currencies (fiat and crypto) with daily updates and a
generous free tier. This module only uses the free /api/rates endpoint.

This module is not the default currency conversion module for a Finance::Quote
object.

=head1 API_KEY

https://unirateapi.com requires users to register and obtain an API key.
The free tier covers the current-rate lookups used by this module.

The API key can be set by setting the environment variable
"UNIRATEAPI_API_KEY" or by providing a 'unirate' hash inside the
'currency_rates' hash to Finance::Quote->new as in the synopsis above.
An explicit value in the hash overrides the environment variable.

=head1 Terms & Conditions

Use of https://unirateapi.com is governed by any terms & conditions of that
site.

Finance::Quote is released under the GNU General Public License, version 2,
which explicitly carries a "No Warranty" clause.

=cut
