#------------------------------------------------------------
# Copyright (C) 2008 RoyaltyShare, Inc.   All Rights Reserved
#------------------------------------------------------------
package Common::CurrencyFormat;

use lib '/app/tools/common/lib';
use Common::Assert;
use Common::XMLObject;
use Common::Log;
use Common::UTF8;

use base 'Common::XMLObject';

# Keyed by ISO 4217 currency code
#
my %gDefs = (
    'MUL' => {
        symbol      => 0x24,
        description => 'multiple currencies',
    },
    'ARS' => {
        symbol      => 0x24,
        description => 'Argentine Peso',
    },
    'AUD' => {
        symbol      => 0x24,
        description => 'Australian Dollar',
    },
    'CAD' => {
        symbol      => 0x24,
        description => 'Canadian Dollar',
    },
    'CHF' => {
        characters  => 'fr',
        description => 'Swiss Francs',
    },
    'CLP' => {
        symbol      => 0x24,
        description => 'Chilean Peso',
    },
    'CNY' => {
        symbol      => 0xa5,
        description => 'Chinese Yuan',
    },
    'COP' => {
        symbol      => 0x24,
        description => 'Columbian Peso',
    },
    'CZK' => {
        characters  => 'Kc ',
        description => 'Czech Republic Koruna',
    },
    'GBP' => {
        symbol      => 0xa3,
        htmlEntity  => "&#163;",
        description => 'British Pound Sterling',
    },
    'USD' => {
        symbol      => 0x24,
        description => 'United States Dollar',
    },
    'EUR' => {
        symbol      => 0x20ac,
        description => 'Euro',
    },
    'ISK' => {
        characters  => 'kr',
        description => 'Icelandic Krona',
    },
    'JMD' => {
        symbol      => 0x24,
        description => 'Jamaican Dollar',
    },
    'JPY' => {
        symbol      => 0xa5,
        description => 'Japanese Yen',
    },
    'LTL' => {
        symbol      => 0x4c,
        description => 'Lithuanian Litai',
    },
    'LVL' => {
        symbol      => 0x4c,
        description => 'Latvian Lati',
    },
    'MXN' => {
        symbol      => 0x24,
        description => 'Mexican Peso',
    },
    'NZD' => {
        symbol      => 0x24,
        description => 'New Zealand Dollar',
    },
    'PLN' => {
        symbol      => 0x7a,
        description => 'Polish Zlotych',
    },
    'QAR' => {
        characters  => 'QR',
        description => 'Qatari Riyal',
    },
    'KRW' => {
        symbol      => 0x20a9,
        description => 'South Korean Won',
    },
    'SEK' => {
        characters  => 'kr',
        description => 'Swedish Krona',
    },
    'ZAR' => {
        characters  => 'R',
        description => 'South African Rand',
    },
    'SIT' => {
        obsolete    => '1',
        characters  => 'SIT',
        description => 'Slovenian Tolar',
    },
    'HRK' => {
        characters  => 'kn',
        description => 'Croatian Kuna',
    },
    'MYR' => {
        characters  => 'RM',
        description => 'Malaysian Ringgits',
    },
    'SGD' => {
        symbol      => 0x24,
        description => 'Singapore Dollars',
    },
    'TRY' => {
        symbol      => 0x20a4,
        description => 'Turkey Liras',
    },
    'EST' => {
        characters  => 'kr',
        description => 'Estonia Liras',
    },
    'DKK' => {
        characters  => 'kr',
        description => 'Danish Krone',
    },
    'NOK' => {
        characters  => 'kr',
        description => 'Norwegian Krone',
    },
    'UYU' => {
        symbol      => 0x24,
        description => 'Uruguayan Peso',
    },
    'BRL' => {
        characters  => 'R$',
        description => 'Brazilian Real',
    },
    'TWD' => {
        symbol      => 0x24,
        description => 'Taiwan Dollar',
    },
    'HKD' => {
        symbol      => 0x24,
        description => 'Hong Kong Dollar',
    },
    'RUB' => {
        characters  => 'RR',
        description => 'Russian Ruble',
    },
    'INR' => {
        symbol      => 0x20b9,
        description => 'Indian Rupee',
    },
    'AED' => {
        characters  => 'AED',
        description => 'United Arab Emirates Dirham',
    },
    'IDR' => {
        characters  => 'Rp',
        description => 'Indonesian Rupiah',
    },
    'ILS' => {
        symbol      => 0x20AA,
        description => 'Israeli Shekel',
    },
    'SAR' => {
        symbol      => 0xFDFC,
        description => 'Saudi Riyal',
    },
    'HUF' => {
        characters  => 'Ft',
        description => 'Hungarian Forint',
    },
    'VEF' => {
        characters  => 'Bs',
        description => 'Venezuelan Bolivar',
    },
    'PEN' => {
        characters  => 'S/.',
        description => 'Peruvian Nuevo Sol',
    },
    'GTQ' => {
        characters  => 'Q',
        description => 'Guatemalan Quetzal',
    },
    'BOB' => {
        characters  => 'Bs',
        description => 'Bolivian Boliviano',
    },
    'CRC' => {
        symbol      => 0x20a1,
        description => 'Costa Rican colon',
    },
    'PYG' => {
        symbol      => 0x8370,
        description => 'Paraguayan guarani',
    },
    'NIO' => {
        characters  => 'C$',
        description => 'Nicaraguan cordoba',
    },
    'HNL' => {
        characters  => 'L',
        description => 'Honduran lempira',
    },
    'BGN' => {
        characters  => 'BGN',
        description => 'Bulgarian lev',
    },
    'PHP' => {
        characters  => 'PHP',
        description => 'Philippine peso',
    },
    'THB' => {
        characters  => 'THB',
        description => 'Thai baht',
    },
    'UAH' => {
        symbol      => 0x20b4,
        description => 'Ukrainian hryvnia',
    },
    'RON' => {
        characters  => 'lei ',
        description => 'Romanian New Leu',
    },
    'VND' => {
        symbol      => 0x20ab,
        description => 'Viet Nam Dong',
    },
    'NGN' => {
        symbol      => 0x20a6,
        description => 'Nigerian naira',
    },
    'KZT' => {
        characters  => "\x{43b}\x{432}",
        description => 'Kazakhstani Tenge',
    },
    'NAD' => {
        symbol      => 0x24,
        description => 'Namibian Dollar',
    },
    'EGP' => {
        characters  => "E\x{a3}",
        description => 'Egyptian Pound',
    },
    'UGX' => {
        characters  => "USh",
        description => 'Ugandan Shilling',
    },
    'PKR' => {
        symbol      => 0x20a8,
        description => 'Pakistan Rupee',
    },
    'DOP' => {
        characters  => 'DOP',
        description => 'Dominican Peso',
    },
    'PAB' => {
        characters  => 'PAB',
        description => 'Panamanian Balboa',
    },
    'TZS' => {
        characters  => 'TZS',
        description => 'Tanzanian Shilling',
    },
);

# This maps country code to currency code, which is an alternate way of constructing these objects.
#
my %gCountryCodeToCurrencyMap = (
    'US' => 'USD',
    'JP' => 'JPY',
    'NZ' => 'NZD',
    'IS' => 'ISD',
    'JM' => 'JMD',
    'EU' => 'EUR',
    'GB' => 'GBP',
    'UK' => 'GBP',
    'CA' => 'CAD',
    'AU' => 'AUD',
    'DE' => 'EUR',
    'FR' => 'EUR',
    'BE' => 'EUR',
    'IT' => 'EUR',
    'CH' => 'CHF',
    'PL' => 'PLN',
    'LV' => 'LVL',
    'LT' => 'LTL',
    'KR' => 'KRW',
    'ZA' => 'ZAR',
    'GR' => 'EUR',
    'NL' => 'EUR',
    'MX' => 'MXN',
    'HR' => 'HRK',
    'MY' => 'MYR',
    'SG' => 'SGD',
    'TR' => 'TRY',
    'EE' => 'EST',
    'UY' => 'UYU',
    'BR' => 'BRL',
    'TW' => 'TWD',
    'HK' => 'HKD',
    'RU' => 'RUB',
    'IN' => 'INR',
    'AE' => 'AED',
    'ID' => 'IDR',
    'IL' => 'ILS',
    'SA' => 'SAR',
    'AT' => 'EUR',
    'ES' => 'EUR',
    'CZ' => 'CZK',
    'HU' => 'HUF',
    'VE' => 'VEF',
    'PE' => 'PEN',
    'GT' => 'GTQ',
    'BO' => 'BOB',
    'CR' => 'CRC',
    'AR' => 'ARS',
    'DK' => 'DKK',
    'FI' => 'EUR',
    'IE' => 'EUR',
    'NO' => 'NOK',
    'PT' => 'EUR',
    'SE' => 'SEK',
    'HN' => 'HNL',
    'NI' => 'NIO',
    'PY' => 'PYG',
    'BG' => 'BGN',
    'PH' => 'PHP',
    'TH' => 'THB',
    'UA' => 'UAH',
    'RO' => 'RON',
    'VN' => 'VND',
    'NG' => 'NGN',
    'KZ' => 'KZT',
    'QA' => 'QAR',
    'PA' => 'PAB',
    'CL' => 'CLP',
    'CO' => 'COP',
    'DO' => 'DOP',
    'TZ' => 'TZS',

    # 'NA' => 'NAD',    # NA is indeed the ISO 3166-1 alpha 2 country code
    # for Namibia, but given its proximity to N/A...
    # we'll leave it out for now.
    'EG' => 'EGP',
    'PK' => 'PKR',
    'SK' => 'EUR',
    'LU' => 'EUR',
    'CY' => 'EUR',
);

sub _init {
    my ( $self, %args ) = @_;

    my $currencyCode = $args{currencyCode};
    if ( !$currencyCode ) {
        assert( $args{countryCode}, "ERROR - you must specify either 'currencyCode' or 'countryCode'" );
        $currencyCode = $gCountryCodeToCurrencyMap{ $args{countryCode} };
    }

    if ( !defined $gDefs{$currencyCode} ) {
        Common::Log::Print( "ERROR - unknown currency code '" . $currencyCode . "'" );
        $self->{Symbol} = '?';
        $self->{CurrencyCode} = ( $currencyCode ? $currencyCode : '???' );
    }

    my $def = $gDefs{$currencyCode};

    # Not all currencies will have utf-8 encoded symbols.
    # Some may just be 1 or more plain characters.
    #
    if ( $def->{symbol} ) {
        $self->{Symbol} = chr( $def->{symbol} );
    } else {
        $self->{Symbol} = $def->{characters};
    }

    $self->{CurrencyCode} = Common::UTF8::Encode($currencyCode);
    $self->{Description}  = $def->{description};

    return $self;
}

sub symbol {
    my ($self) = @_;
    return $self->{Symbol};
}

sub htmlEntity {
    my ($self) = @_;
    print STDERR "in Locale->htmlEntity, currencyCode: $currencyCode\n";
    if ( defined $gDefs{$currencyCode} ) {
        if ( defined $gDefs{$currencyCode}{htmlEntity} ) {
            print STDERR "htmlEntity: $gDefs{$currencyCode}{htmlEntity}\n";
            return $gDefs{$currencyCode}{htmlEntity};
        } else {
            Common::Log::Print( "ERROR - mis-configured currency code '" . $currencyCode . "' - no html entity defined" );
        }
    }
}

sub description {
    my ($self) = @_;
    return $self->{Description};
}

sub currencyCode {
    my ($self) = @_;
    return $self->{CurrencyCode};
}

# !!! To simplify some things, we'll have some static accessors here as well.
#
sub Symbol {
    my ($currencyCode) = @_;

    if ( defined $gDefs{$currencyCode} ) {
        if ( defined $gDefs{$currencyCode}{symbol} ) {
            return chr( $gDefs{$currencyCode}{symbol} );
        } elsif ( defined $gDefs{$currencyCode}{characters} ) {
            return $gDefs{$currencyCode}{characters};
        } else {
            Common::Log::Print( "ERROR - mis-configured currency code '" . $currencyCode . "' - no symbol or characters defined" );
        }
    }

    Common::Log::Print( "ERROR - unknown currency code '" . $currencyCode . "'" );
    return '?';
}

sub CodeIsValid {
    my ($currencyCode) = @_;

    return 1 if ( $gDefs{$currencyCode} );
    return 0;
}

sub List {
    my @currencyFormatList;

    foreach my $key ( sort keys %gDefs ) {
        my $currencyFormat = Common::CurrencyFormat->new( currencyCode => $key );
        push( @currencyFormatList, $currencyFormat );
    }

    return @currencyFormatList;
}

package Common::CurrencyFormatList;

use Common::FormObject;
use base 'Common::FormObject';

sub _init {
    my ( $self, %args ) = @_;

    $self->SUPER::_init(%args);

    $self->{CurrencyFormat} = [];

    foreach my $key ( sort keys %gDefs ) {
        push @{ $self->{CurrencyFormat} }, Common::CurrencyFormat->new( currencyCode => $key );
    }

    return $self;
}

1;
