<?php

defined('ABSPATH') || exit;

class PPCP_Paypal_Checkout_For_Woocommerce_DCC_Validate {

    protected static $_instance = null;
    public $country;

    public static function instance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * The matrix which countries and currency combinations can be used for DCC.
     *
     */
    private $allowed_country_currency_matrix = array(
        'AU' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'AT' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'BE' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'BG' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'CA' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'CY' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'CZ' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'DK' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'EE' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'FI' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'FR' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'DE' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'GR' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'HU' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'IE' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'IT' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'JP' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'LV' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'LI' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'LT' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'LU' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'MT' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'MX' => array(
            'MXN',
        ),
        'NL' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'PL' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'PT' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'RO' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'SK' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'SI' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'ES' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'SE' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'GB' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
        'US' => array(
            'AUD',
            'CAD',
            'EUR',
            'GBP',
            'JPY',
            'USD',
        ),
        'NO' => array(
            'AUD',
            'BRL',
            'CAD',
            'CHF',
            'CZK',
            'DKK',
            'EUR',
            'GBP',
            'HKD',
            'HUF',
            'ILS',
            'JPY',
            'MXN',
            'NOK',
            'NZD',
            'PHP',
            'PLN',
            'SEK',
            'SGD',
            'THB',
            'TWD',
            'USD',
        ),
    );

    /**
     * Which countries support which credit cards.
     */
    private $country_card_matrix = array(
        'AU' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('AUD'),
        ),
        'AT' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'BE' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD', 'CAD'),
        ),
        'BG' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'CY' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'CZ' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('CZK'),
        ),
        'DE' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'DK' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('DKK'),
        ),
        'EE' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'ES' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'FI' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'FR' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'GB' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('GBP', 'USD'),
        ),
        'GR' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'HU' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('HUF'),
        ),
        'IE' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'IT' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'US' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('USD'),
            'discover' => array('USD'),
        ),
        'CA' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('CAD'),
            'jcb' => array('CAD'),
        ),
        'LI' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'LT' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'LU' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'LV' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD'),
        ),
        'MT' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'MX' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'NL' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD'),
        ),
        'NO' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array(),
        ),
        'PL' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD', 'GBP', 'PLN'),
        ),
        'PT' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD', 'CAD', 'GBP'),
        ),
        'RO' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'USD'),
        ),
        'SE' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'SEK'),
        ),
        'SI' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR'),
        ),
        'SK' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('EUR', 'GBP'),
        ),
        'JP' => array(
            'mastercard' => array(),
            'visa' => array(),
            'amex' => array('JPY'),
            'jcb' => array('JPY'),
        ),
    );

    /**
     * Returns whether DCC can be used in the current country and the current currency used.
     */
    public function for_country_currency($country = null) {
        try {
            if ($country === null) {
                $country = $this->country();
            }
            $currency = get_woocommerce_currency();
            if (!in_array($country, array_keys($this->allowed_country_currency_matrix), true)) {
                return false;
            }
            $applies = in_array($currency, $this->allowed_country_currency_matrix[$country], true);
            return $applies;
        } catch (Exception $ex) {
            
        }
    }

    /**
     * Returns credit cards, which can be used.
     */
    public function valid_cards() {
        try {
            $this->country = $this->country();
            $cards = array();
            if (!isset($this->country_card_matrix[$this->country])) {
                return $cards;
            }

            $supported_currencies = $this->country_card_matrix[$this->country];
            foreach ($supported_currencies as $card => $currencies) {
                if ($this->can_process_card($card)) {
                    $cards[] = $card;
                }
            }
            if (in_array('amex', $cards, true)) {
                $cards[] = 'american-express';
            }
            if (in_array('mastercard', $cards, true)) {
                $cards[] = 'master-card';
            }
            return $cards;
        } catch (Exception $ex) {
            
        }
    }

    /**
     * Whether a card can be used or not.
     */
    public function can_process_card($card) {
        try {
            $this->country = $this->country();
            if (!isset($this->country_card_matrix[$this->country])) {
                return false;
            }
            if (!isset($this->country_card_matrix[$this->country][$card])) {
                return false;
            }
            $supported_currencies = $this->country_card_matrix[$this->country][$card];
            $currency = get_woocommerce_currency();
            return empty($supported_currencies) || in_array($currency, $supported_currencies, true);
        } catch (Exception $ex) {
            
        }
    }

    public function country() {
        try {
            $region = wc_get_base_location();
            $country = $region['country'];
            return $country;
        } catch (Exception $ex) {
            
        }
    }
}
