'United States',
        self::REGION_UK => 'United Kingdom',
        self::REGION_DE => 'Germany',
    );
    /**
     *
     * accepted currencies for each region
     *
     * @var array
     */
    protected $_currencies = array(
        self::REGION_US => 'USD',
        self::REGION_UK => 'GBP',
        self::REGION_DE => 'EUR',
    );
    /**
     *
     * view object
     *
     * @var \Cube\View
     */
    protected $_view;
    /**
     * amazon payments description
     */
    protected $_description = 'Click to pay using Amazon Payments Checkout.';
    /**
     *
     * class constructor
     *
     * @param int $userId
     */
    public function __construct($userId = null)
    {
        parent::__construct(self::NAME, $userId);
    }
    /**
     *
     * check if the gateway is enabled
     *
     * @return bool
     */
    public function enabled()
    {
        if (!empty($this->_data[self::MERCHANT_ID]) && !empty($this->_data[self::ACCESS_KEY]) && !empty($this->_data[self::SECRET_KEY])) {
            return true;
        }
        return false;
    }
    /**
     *
     * get setup form elements
     *
     * @return array
     */
    public function getElements()
    {
        $translate = $this->getTranslate();
        return array(
            array(
                'form_id'     => 'AmazonPayments',
                'id'          => self::MERCHANT_ID,
                'element'     => 'text',
                'label'       => $this->_('Merchant ID'),
                'description' => $this->_('Found in - Amazon Payments > Settings > Account Info > Checkout Pipeline Settings'),
                'attributes'  => array(
                    'class' => 'form-control input-medium',
                ),
            ),
            array(
                'form_id'     => 'AmazonPayments',
                'id'          => self::ACCESS_KEY,
                'element'     => 'text',
                'label'       => $this->_('AWS Access Key ID'),
                'description' => $this->_('Enter your access key id (public)'),
                'attributes'  => array(
                    'class' => 'form-control input-medium',
                ),
            ),
            array(
                'form_id'     => 'AmazonPayments',
                'id'          => self::SECRET_KEY,
                'element'     => 'text',
                'label'       => $this->_('AWS Secret Access Key'),
                'description' => $translate->_('Enter your secret access key (private)
Amazon Payments IPN URL:
') . $this->getIpnUrl(),
                'attributes'  => array(
                    'class' => 'form-control input-medium',
                ),
            ),
            array(
                'form_id'      => 'AmazonPayments',
                'id'           => self::REGION,
                'element'      => 'select',
                'label'        => $this->_('Region'),
                'description'  => $this->_('Select the region that applies to your Amazon Payments account.'),
                'multiOptions' => $this->_regions,
                'attributes'   => array(
                    'class' => 'form-control input-medium',
                ),
            )
        );
    }
    /**
     *
     * set transaction amount
     * convert all amounts to USD before going to the payment page
     *
     * @param string $amount
     *
     * @throws \RuntimeException
     * @return $this
     */
    public function setAmount($amount)
    {
        $currency = $this->getCurrency();
        if (empty($currency)) {
            $translate = $this->getTranslate();
            throw new \RuntimeException($translate->_("Please set the currency before setting the amount."));
        }
        $acceptedCurrency = $this->_currencies[$this->_getActiveRegion()];
        if ($currency != $acceptedCurrency) {
            $currenciesService = new CurrenciesService();
            $amount = $currenciesService->convertAmount($amount, $currency, $acceptedCurrency);
            $this->setCurrency($acceptedCurrency);
        }
        parent::setAmount($amount);
        return $this;
    }
    /**
     *
     * @return array
     */
    public function formElements()
    {
        $translate = $this->getTranslate();
        $view = Front::getInstance()->getBootstrap()->getResource('view');
        /** @var \Cube\View\Helper\Script $scriptHelper */
        $scriptHelper = $view->getHelper('script');
        switch ($this->_getActiveRegion()) {
            case self::REGION_US:
                $scriptHelper->addBodyCode("");
                break;
            case self::REGION_UK:
                $scriptHelper->addBodyCode('');
                // UK sandbox.
                // $scriptHelper->addBodyCode('');
                break;
            case self::REGION_DE:
                $scriptHelper->addBodyCode('');
                break;
        }
        return array(
            array(
                'id'       => self::MERCHANT_ID,
                'value'    => $this->_data[self::MERCHANT_ID],
                'element'  => 'hidden',
                'bodyCode' => "",
            ),
            array(
                'id'      => 'item_sku_1',
                'value'   => $this->getTransactionId(),
                'element' => 'hidden',
            ),
            array(
                'id'      => 'item_title_1',
                'value'   => $this->_shortenString($this->getName(), 80),
                'element' => 'hidden',
            ),
            array(
                'id'      => 'item_price_1',
                'value'   => $this->getAmount(),
                'element' => 'hidden',
            ),
            array(
                'id'      => 'item_quantity_1',
                'value'   => '1',
                'element' => 'hidden',
            ),
            array(
                'id'      => 'currency_code',
                'value'   => $this->getCurrency(),
                'element' => 'hidden',
            ),
            array(
                'id'      => 'merchant_signature', // cart hash for signed carts
                'value'   => $this->_encryptAndEncode(
                    $this->_createHash()),
                'element' => 'hidden',
            ),
            array(
                'id'      => self::ACCESS_KEY,
                'value'   => $this->_data[self::ACCESS_KEY],
                'element' => 'hidden',
            ),
        );
    }
    public function getPostUrl()
    {
        return self::POST_URL;
    }
    /**
     *
     * process ipn
     *
     * @param \Cube\Controller\Request\AbstractRequest $request
     *
     * @return bool
     */
    public function processIpn(AbstractRequest $request)
    {
        $response = false;
        if ($request->isPost()) {
            $UUID = $request->getParam('UUID');
            $Signature = $request->getParam('Signature'); // if empty, we have an unsigned cart, but our carts must all be signed
            $Timestamp = $request->getParam('Timestamp');
            $NotificationData = stripslashes($request->getParam('NotificationData')); // need to parse it as xml or something.
            $NotificationType = $request->getParam('NotificationType');
            $xmlObject = new Xml();
            $xmlObject->setData(
                urldecode($NotificationData));
            $orderDetails = $xmlObject->getData('ProcessedOrder');
            $this->setGatewayPaymentStatus($NotificationType)
                ->setGatewayTransactionCode($UUID);
            $generatedSignature = $this->_encryptAndEncode($UUID . $Timestamp);
            if (strcmp($generatedSignature, $Signature) === 0 || empty($Signature)) {
                $this->setTransactionId($orderDetails['ProcessedOrderItems']['ProcessedOrderItem'][0]['SKU'])
                    ->setAmount($orderDetails['ProcessedOrderItems']['ProcessedOrderItem'][0]['Price']['Amount'])
                    ->setCurrency($orderDetails['ProcessedOrderItems']['ProcessedOrderItem'][0]['Price']['CurrencyCode']);
                if ($NotificationType == 'OrderReadyToShipNotification') {
                    $response = true;
                }
            }
            else {
                $this->setGatewayPaymentStatus('Invalid Signature');
            }
        }
        return $response;
    }
    /**
     *
     * generates the required hash -- it gets generated exactly list on amazon's signed cart demo
     *
     * @return string
     */
    private function _createHash()
    {
        $data = array(
            self::MERCHANT_ID => $this->_data[self::MERCHANT_ID],
            'item_sku_1'      => $this->getTransactionId(),
            'item_title_1'    => $this->getName(),
            'item_price_1'    => $this->getAmount(),
            'item_quantity_1' => '1',
            'currency_code'   => $this->getCurrency(),
            self::ACCESS_KEY  => $this->_data[self::ACCESS_KEY],
        );
        ksort($data);
        $crypt = null;
        foreach ($data as $key => $value) {
            $crypt .= $key . '=' . rawurlencode($value) . '&';
        }
        return $crypt;
    }
    /**
     *
     * encrypt and encode string for signed carts
     *
     * @param string $string
     *
     * @return string
     */
    private function _encryptAndEncode($string)
    {
        return base64_encode(hash_hmac(self::HMAC_SHA1_ALGORITHM, $string, $this->_data[self::SECRET_KEY], true));
    }
    /**
     *
     * get active region
     *
     * @return string
     */
    protected function _getActiveRegion()
    {
        if (isset($this->_data[self::REGION])) {
            $region = $this->_data[self::REGION];
            if (in_array($region, array_keys($this->_regions))) {
                return $region;
            }
        }
        return self::REGION_US;
    }
}