<?php

/**
 *
 * @category MultiSafepay
 * @package  MultiSafepay_Msp
 */
require_once(Mage::getBaseDir('lib') . DS . 'multisafepay' . DS . 'MultiSafepay.combined.php');

class MultiSafepay_Msp_Model_Checkout extends Mage_Payment_Model_Method_Abstract
{
    protected $_code = "mspcheckout";
    protected $_settings = 'mspcheckout';
    protected $_quote;
    protected $_storeId = null;
    protected $total_amount = 0;
    protected $api;
    protected $base;
    protected $_isGateway = false;
    protected $_canAuthorize = true;
    protected $_canCapture = true;
    protected $_canCapturePartial = true;
    protected $_canRefund = false;
    protected $_canRefundInvoicePartial = false;
    protected $_canVoid = false;
    protected $_canUseInternal = false;
    protected $_canUseForMultishipping = false;
    protected $_fcoapp = false;
    protected $_cachedShippingInfo = array(); // Cache of possible shipping carrier-methods combinations per storeId

    public function canUseCheckout()
    {
        return false;
    }

    // Need this for 1.3.x.x, or it will always be true
    // Disabled, needs testing. Comment mentioned this was for 1.3.x.x and that version is no longer supported by this release
    /*
        public function isAvailable($quote = null) {
            // Maybe call parent for higher versions?
            return (bool) (int) $this->getConfigData('active', ($quote ? $quote->getStoreId() : null));
        }
    */

    /**
     * Returns an instance of the Base
     */
    public function getBase($id = null)
    {
        if ($this->base) {
            if ($id) {
                $this->base->setLogId($id);
                $this->base->setLockId($id);
            }

            return $this->base;
        }

        $config = Mage::getStoreConfig($this->_settings . "/settings", $this->_storeId);

        $this->base = Mage::getSingleton("msp/base");
        $this->base->setConfigObject($config);
        $this->base->setLogId($id);
        $this->base->setLockId($id);

        return $this->base;
    }

    /**
     * Returns an instance of the Api
     */
    public function getApi($id = null)
    {
        if ($this->api) {
            if ($id) {
                $this->getBase($id);
            }

            return $this->api;
        }

        $base = $this->getBase($id);
        $this->api = $base->getApi();

        return $this->api;
    }

    /**
     * Start checkout
     */
    public function startCheckout()
    {
        $storeId = Mage::app()->getStore()->getStoreId();
        $storeName = Mage::app()->getStore()->getName();
        $this->_storeId = $storeId;

        $session = Mage::getSingleton('checkout/session');
        $this->_quote = $session->getQuote();

        $quoteId = $this->_quote->getId();
        $api = $this->getApi($quoteId);

        $this->getBase()->log('startCheckout');

        $api->merchant['notification_url'] = Mage::getUrl("msp/checkout/notification", array("_secure" => true)) . "?type=initial";
        $api->merchant['cancel_url'] = Mage::getUrl("checkout/cart/", array("_secure" => true));
        $api->merchant['redirect_url'] = Mage::getUrl("msp/checkout/return", array("_secure" => true));

        $api->transaction['id'] = $quoteId;
        $api->transaction['currency'] = 'EUR';
        $api->transaction['amount'] = intval((string) ($this->_quote->getBaseGrandTotal() * 100)); // may include shipping costs?
        $api->transaction['description'] = Mage::helper("msp")->__("Order") . ' #' . $quoteId . Mage::helper("msp")->__("@") . $storeName;
        $api->customer['locale'] = Mage::app()->getLocale()->getDefaultLocale();

        $customerSession = Mage::getSingleton('customer/session');
        $customer = $customerSession->getCustomer();

        $billing = $customer->getPrimaryBillingAddress();
        $shipping = $customer->getPrimaryShippingAddress();

        $lang = $this->getConfigData('lang');
        if (empty($lang)) {
            $api->customer['locale'] = Mage::app()->getLocale()->getLocaleCode(); // Mage::app()->getLocale()->getDefaultLocale(); $lang
        }
        $api->customer['locale'] = $lang;

        if ($billing) {
            $this->api->parseCustomerAddress($billing->getStreet(1));

            if ($this->api->customer['housenumber'] == '') {
                $this->api->customer['housenumber'] = $billing->getStreet(2);
                $this->api->customer['address1'] = $billing->getStreet(1);
            }

            if ($billing->getStreet(3) != '') {
                $this->api->customer['housenumber'] .= ' ' . $billing->getStreet(3);
            }

            $api->customer['firstname'] = $billing->getFirstname();
            $api->customer['lastname'] = $billing->getLastname();
            $api->customer['address2'] = $billing->getStreet(2);
            $api->customer['zipcode'] = $billing->getPostcode();
            $api->customer['city'] = $billing->getCity();
            $api->customer['state'] = $billing->getState();
            $api->customer['country'] = $billing->getCountry();
            $api->customer['phone'] = $billing->getTelephone();
            $api->customer['email'] = $customer->getEmail();
        }

        if ($shipping) {
            $api->parseDeliveryAddress($shipping->getStreet(1));

            if ($shipping->getStreet(3) != '') {
                $api->delivery['housenumber'] .= ' ' . $shipping->getStreet(3);
            }
            $api->delivery['firstname'] = $shipping->getFirstname();
            $api->delivery['lastname'] = $shipping->getLastname();
            $api->delivery['address2'] = $shipping->getStreet(2);
            $api->delivery['zipcode'] = $shipping->getPostcode();
            $api->delivery['city'] = $shipping->getCity();
            $api->delivery['state'] = $shipping->getState();
            $api->delivery['country'] = $shipping->getCountry();
            $api->delivery['phone'] = $shipping->getTelephone();
            $api->delivery['email'] = $customer->getEmail();
        }
        $api->customer['referrer'] = $_SERVER['HTTP_REFERER'];
        $api->customer['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
        $api->customer['ipaddress'] = $_SERVER['REMOTE_ADDR'];
        $this->getItems();

        $table = new MspAlternateTaxTable();
        $table->name = 'BTW0';
        $rule = new MspAlternateTaxRule('0.00');
        $table->AddAlternateTaxRules($rule);
        $this->api->cart->AddAlternateTaxTables($table);

        $discount_amount = $this->_quote->getData();
        $discount_amount_final = $discount_amount['base_subtotal'] - $discount_amount['subtotal_with_discount'];
        $discount_amount_final = number_format($discount_amount_final, 4, '.', '');

        // Add discount line item
        if ($discount_amount_final != 0) {
            $c_item = new MspItem('Discount', 'Discount', 1, -$discount_amount_final, 'KG', 0); // Todo adjust the amount to cents, and round it up.
            $c_item->SetMerchantItemId('Discount');
            $c_item->SetTaxTableSelector('BTW0');
            $api->cart->AddItem($c_item);
        }

        $this->getShipping(); //
        $this->_getShippingRates();
        $this->setTaxes();
        $this->getCustomFieldsFromFile();

        if ($this->getSectionConfigData('checkout_custom_fields/fco_postnl')) {
            $title = 'Post NL';
            $price = $this->getSectionConfigData('checkout_custom_fields/fco_postnl_amount');
            //$price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);
            $provider = 'PostNL';
            $shipping = new MspPickup($title, $price, $provider);
            $this->api->cart->AddShipping($shipping);
        }

        if ($this->getSectionConfigData('checkout_custom_fields/company_active')) {
            $this->getCompanyField();
        }

        if ($this->getSectionConfigData('checkout_custom_fields/agreements_active')) {
            $this->getAgreementField();
        }

        $this->getExtraFields();

        $url = $api->startJSONCheckout();

        $this->getBase($quoteId)->log($api->request_xml);
        $this->getBase($quoteId)->log($api->reply_xml);

        if ($api->error) {
            $this->getBase()->log("Error %s: %s", $api->error_code, $api->error);
            echo "Error " . $api->error_code . ": " . $api->error;
            exit();
        }

        $this->getBase()->log('Payment URL: %s', $url);

        return $url;
    }

    public function getAgreementField()
    {
        $field = new MspCustomField('acceptagreements', 'checkbox', '');

        // Description
        $config_url = $this->getSectionConfigData('checkout_custom_fields/agreements_url');
        if (!empty($config_url)) {
            $link = $config_url;
        } else {
            $link = Mage::getUrl("msp/checkout/agreements/", array("_secure" => true));
        }

        $description = array(
            'nl' => 'Ik ga akkoord met de <a href="' . $link . '" target="_blank">algemene voorwaarden</a>',
            'en' => 'I accept the <a href="' . $link . '" target="_blank">terms and conditions</a>',
        );
        $field->descriptionRight = array('value' => $description);

        // Validation
        $error = array(
            'nl' => 'U dient akkoord te gaan met de algemene voorwaarden',
            'en' => 'Please accept the terms and conditions',
        );
        $validation = new MspCustomFieldValidation('regex', '^[1]$', $error);
        $field->AddValidation($validation);

        $this->api->fields->AddField($field);
    }

    public function getExtraFields()
    {
        $option = $this->getSectionConfigData('checkout_custom_fields/company_active');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('companyname', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_salutation');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('salutation', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_sex');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('sex', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_comment');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('comment', 2 == $option);
            $this->api->fields->AddField($field);
        }

        // Checkbox
        if ($this->getSectionConfigData('checkout_custom_fields/xtra_newsletter')) {
            $field = new MspCustomField();
            $field->SetStandardField('newsletter', 1);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_vatnumber');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('vatnumber', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_birthday');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('birthday', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_phone');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('phonenumber', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_chamberofcommerce');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('chamberofcommerce', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_passportnumber');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('passportnumber', 2 == $option);
            $this->api->fields->AddField($field);
        }

        $option = $this->getSectionConfigData('checkout_custom_fields/xtra_driverslicense');
        if ($option) {
            $field = new MspCustomField();
            $field->SetStandardField('driverslicense', 2 == $option);
            $this->api->fields->AddField($field);
        }
    }

    public function qwindoNotification($data, $response)
    {
        /** @var $quote Mage_Sales_Model_Quote */
        $quote = Mage::getSingleton('sales/quote')->load($data['transaction_id']);
        $base = $this->getBase($data['transaction_id']);
        $quote_data = $quote->getData();
        $this->_storeId = $quote->getStoreId();
        $this->_createQwindoOrder($data, $response);

        // Get the order
        $order = Mage::getSingleton('sales/order')->loadByAttribute('ext_order_id', $data['transaction_id']);

        if (!$order) {
            return false;
        } else {
            $base->updateQwindoStatus($data['status'], $data);
            return true;
        }
    }

    /**
     * Notification
     */
    public function notification($quoteId, $initial = false)
    {
        /** @var $quote Mage_Sales_Model_Quote */
        $quote = Mage::getSingleton('sales/quote')->load($quoteId);
        $data = $quote->getData();

        // CHECK FOR FCO APP. When the FCO app is used, the transactionid is no valid quote ID, resulting in an emtpy quote.
        if (empty($data) || empty($data['customer_id'])) {
            $this->_fcoapp = true;
        }

        $this->_storeId = $quote->getStoreId();
        $base = $this->getBase($quoteId);

        // TEMP locking disabled because of check on redirect url
        // Check lock
        /*
            if ($base->isLocked()) {
                $base->preventLockDelete();

                if ($initial) {
                    return;
                } else {
                    echo 'locked';
                    exit();
                }
            }
            // Lock
            $base->lock();
        */
        $base->log('notification');

        $api = $this->getApi();
        $api->transaction['id'] = $quoteId;
        $status = $api->getStatus();

        /** @var $helper MultiSafepay_Msp_Helper_Data */
        $helper = Mage::helper('msp');
        $isRestored = $helper->restoreCart($quote, $status);
        $base->log("Quote was restored: " . ($isRestored ? 'TRUE' : 'FALSE'));

        $base->log($api->request_xml);
        $base->log($api->reply_xml);

        if ($api->error) {
            $base->log("Error %s: %s", $api->error_code, $api->error);
            echo "Error " . $api->error_code . ": " . $api->error;
            $base->unlock();
            exit();
        }

        if ($api->details['ewallet']['id'] == '') {
            return true;
        } else {
            $this->_createOrder($quoteId);
        }

        $base->log("Quote ID: $quoteId");
        // Get the order
        $order = Mage::getSingleton('sales/order')->loadByAttribute('ext_order_id', $quoteId);
        if (!$order) {
            $this->getBase()->log("Failed to load order");
            echo 'Failed to load order ' . $quoteId;
        }
        $ret = $base->updateStatus($order, $status, $api->details);
        // Cancel order if needed
        if ($base->cancel) {
            $order->cancel;
        }

        // Unlock
        $base->unlock();

        return $ret;
    }

    public function getCustomFieldsFromFile()
    {
        $ret = '';
        $file = dirname(dirname(__FILE__)) . DS . 'etc' . DS . 'customfields.xml';
        if (is_readable($file)) {
            $ret = @file_get_contents($file);
        }
        $this->api->fields->SetRaw($ret);
    }

    protected function getItems()
    {
        foreach ($this->_quote->getAllItems() as $item) {
            if ($item->getParentItem()) {
                continue;
            }
            $taxClass = ($item->getTaxClassId() == 0 ? 'none' : $item->getTaxClassId());
            $weight = (float) $item->getWeight();

            // Name and options
            $itemName = $item->getName();
            $options = $this->getProductOptions($item);
            if (!empty($options)) {
                $optionString = '';
                foreach ($options as $option) {
                    $optionString = $option['label'] . ": " . $option['print_value'] . ",";
                }
                $optionString = substr($optionString, 0, -1);

                $itemName .= ' (';
                $itemName .= $optionString;
                $itemName .= ')';
            }

            // Magento uses the rounded number, so we do too
            $price = round($item->getBaseCalculationPrice(), 2);
            // Code below was disabled, this is now activated again to avoid rounding problems
            if (Mage::helper("Tax")->priceIncludesTax()) {
                $priceIncl = $item->getBasePriceInclTax();
                $taxRate = $item->getTaxPercent();
                $price = ($priceIncl / (1 + ($taxRate / 100)));
            }

            // $price = number_format($item->getPrice(), 4, '.', '');
            $this->total_amount += ($item->getBasePriceInclTax() * $item->getQty());
            // Create item
            $c_item = new MspItem($itemName, $item->getDescription(), $item->getQty(), $price, 'KG', $item->getWeight());
            $c_item->SetMerchantItemId($item->getSku());
            $c_item->SetTaxTableSelector($taxClass);
            $this->api->cart->AddItem($c_item);
        }
    }

    public function getProductOptions($item)
    {
        $options = array();
        if ($optionIds = $item->getOptionByCode('option_ids')) {
            $options = array();
            foreach (explode(',', $optionIds->getValue()) as $optionId) {
                if ($option = $item->getProduct()->getOptionById($optionId)) {
                    $quoteItemOption = $item->getOptionByCode('option_' . $option->getId());
                    $group = $option->groupFactory($option->getType())->setOption($option)->setQuoteItemOption($quoteItemOption);
                    $options[] = array(
                        'label' => $option->getTitle(),
                        'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()),
                        'print_value' => $group->getPrintableOptionValue($quoteItemOption->getValue()),
                        'option_id' => $option->getId(),
                        'option_type' => $option->getType(),
                        'custom_view' => $group->isCustomizedView()
                    );
                }
            }
        }

        if ($addOptions = $item->getOptionByCode('additional_options')) {
            $options = array_merge($options, unserialize($addOptions->getValue()));
        }

        return $options;
    }

    protected function getShipping()
    {
        if (!$this->getFreeShipping()) {
            $this->getFlatRateShipping();
            $this->getTableRateShipping();
            $this->getPickup();
        }
    }

    protected function _getShippingRates()
    {
        $this->_getFreeShippingRates();
        $this->_getFlatRateShippingRates();
        $this->_getAvailableShippingRates(array('flatrate_flatrate', 'freeshipping_freeshipping'));
    }

    protected function _getFreeShippingRates()
    {
        if (!Mage::getStoreConfigFlag('carriers/freeshipping/active')) {
            return $this;
        }

        $config = Mage::getStoreConfig('carriers/freeshipping');

        $allowSpecific = $config['sallowspecific'];
        $specificCountries = $config['specificcountry'];
        $title = $config['title'];
        $name = $config['name'];
        $price = $config['free_shipping_subtotal'];

        if ($price <= $this->total_amount) {
            $shipping_method = new MspFlatRateShipping($title . ' - ' . $name, '0.00');
            if ($allowSpecific == 1 && $specificCountries) {
                $filter = new MspShippingFilters();
                foreach (explode(',', $specificCountries) as $country) {
                    $filter->AddAllowedPostalArea($country);
                }
                $shipping_method->AddShippingRestrictions($filter);
            }
            $this->api->cart->AddShipping($shipping_method);
        }

        return $this;
    }

    protected function _getFlatRateShippingRates()
    {
        if (!Mage::getStoreConfigFlag('carriers/flatrate/active')) {
            return $this;
        }

        $config = Mage::getStoreConfig('carriers/flatrate');

        $allowSpecific = $config['sallowspecific'];
        $specificCountries = isset($config['specificcountry']) ? $config['specificcountry'] : '';
        $title = $config['title'];
        $name = $config['name'];
        $type = $config['type'];
        $price = $config['price'];
        $handlingType = $config['handling_type'];
        $handlingFee = isset($config['handling_fee']) ? $config['handling_fee'] : 0;

        switch ($type) {
            case 'O':
                $shippingPrice = $price;
                break;
            case 'I':
                $shippingPrice = $price * Mage::getSingleton('checkout/cart')->getSummaryQty();
                break;
            default:
                $shippingPrice = 0;
                break;
        }

        if ($handlingFee) {
            switch ($handlingType) {
                case 'F':
                    $shippingPrice = $shippingPrice + $handlingFee;
                    break;
                case 'P':
                    $shippingPrice = $shippingPrice + $shippingPrice * $handlingFee;
                    break;
            }
        }

        $shipping_method = new MspFlatRateShipping($title . ' - ' . $name, number_format($shippingPrice, '2', '.', ''));
        if ($allowSpecific == 1 && $specificCountries) {
            $filter = new MspShippingFilters();
            foreach (explode(',', $specificCountries) as $country) {
                $filter->AddAllowedPostalArea($country);
            }
            $shipping_method->AddShippingRestrictions($filter);
        }
        $this->api->cart->AddShipping($shipping_method);

        return $this;
    }

    protected function _getAvailableShippingRates($exceptMethods)
    {
        /** @var $quote Mage_Sales_Model_Quote */
        $quote = Mage::getSingleton('sales/quote');

        /** @var $shippingAddress Mage_Sales_Model_Quote_Address */
        $shippingAddress = $quote->getShippingAddress();
        $shippingAddress->setCountryId(null);
        $shippingAddress->setPostcode(null);
        $shippingAddress->setCollectShippingRates(true);

        $rates = $shippingAddress->collectShippingRates()->getGroupedAllShippingRates();

        foreach ($rates as $carrier) {
            foreach ($carrier as $rate) {
                if (!in_array($rate->getCode(), $exceptMethods)) {
                    $shipping_method = new MspFlatRateShipping($rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle(), number_format($rate->getPrice(), '2', '.', ''));
                    /*
                        $config = Mage::getStoreConfig('carriers/'.$rate->getCode());
                        if ($allowSpecific == 1 && $specificCountries) {
                            $filter = new MspShippingFilters();
                            foreach (explode(',', $specificCountries) as $country) {
                                $filter->AddAllowedPostalArea($country);
                            }
                            $shipping_method->AddShippingRestrictions($filter);
                        }
                    */
                    $this->api->cart->AddShipping($shipping_method);
                }
            }
        }

        return $this;
    }

    /**
     * @return bool
     */
    public function getFreeShipping()
    {
        if (!$this->getSectionConfigData('freeshipping/active')) {
            return false;
        }

        $allowSpecific = $this->getSectionConfigData('freeshipping/sallowspecific');
        $specificCountries = $this->getSectionConfigData('freeshipping/specificcountry');
        $title = $this->getSectionConfigData('freeshipping/title');
        $price = $this->getSectionConfigData('freeshipping/free_shipping_subtotal');

        $free_price = '0.00';

        if ($price <= $this->total_amount) {
            $shipping_method = new MspFlatRateShipping($title, $free_price);
            if ($allowSpecific == 1 && $specificCountries) {
                $filter = new MspShippingFilters();
                foreach (explode(',', $specificCountries) as $country) {
                    $filter->AddAllowedPostalArea($country);
                }
                $shipping_method->AddShippingRestrictions($filter);
            }
            $this->api->cart->AddShipping($shipping_method);

            // Shipping is free so return true to skip the other shipping methods
            return true;
        }

        return false;
    }

    /**
     * @return void
     */
    public function getPickup()
    {
        if (!$this->getSectionConfigData('checkout_shipping_pickup/active')) {
            return;
        }
        $title = $this->getSectionConfigData('checkout_shipping_pickup/title');
        $price = $this->getSectionConfigData('checkout_shipping_pickup/price');
        $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);

        $shipping = new MspPickup($title, $price);
        $this->api->cart->AddShipping($shipping);
    }

    /**
     * @return void
     */
    public function getFlatRateShipping()
    {
        if (!$this->getSectionConfigData('checkout_shipping_flatrate/active')) {
            return;
        }

        // Flat rate
        for ($xml = '', $i = 1; $i <= 3; $i++) {
            $title = $this->getSectionConfigData('checkout_shipping_flatrate/title_' . $i);
            $price = $this->getSectionConfigData('checkout_shipping_flatrate/price_' . $i);

            if (empty($title) || empty($price)) {
                continue;
            }

            $allowSpecific = $this->getSectionConfigData('checkout_shipping_flatrate/sallowspecific_' . $i);
            $specificCountries = $this->getSectionConfigData('checkout_shipping_flatrate/specificcountry_' . $i);

            $price = number_format($price, 2, '.', '');
            $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);

            $shipping = new MspFlatRateShipping($title, $price);
            if ($allowSpecific == 1 && $specificCountries) {
                $filter = new MspShippingFilters();
                foreach (explode(',', $specificCountries) as $country) {
                    $filter->AddAllowedPostalArea($country);
                }
                $shipping->AddShippingRestrictions($filter);
            }
            $this->api->cart->AddShipping($shipping);
        }
    }

    /**
     * @return array
     *
     */
    public function getTableRateCountries()
    {
        $countries = array();
        $websiteId = $this->_quote->getStore()->getWebsiteId();

        $prefix = Mage::getConfig()->getTablePrefix();
        $sql = "SELECT DISTINCT dest_country_id FROM " . $prefix . "shipping_tablerate WHERE website_id = '" . $websiteId . "'";

        //$sql = "SELECT DISTINCT dest_country_id FROM shipping_tablerate WHERE website_id = '".$websiteId."'";

        $getData = Mage::getSingleton('core/resource')->getConnection('core_read')->fetchAll($sql);

        foreach ($getData as $row) {
            $countries[] = $row['dest_country_id'];
        }

        return $countries;
    }

    /**
     * @return void
     */
    public function getTableRateShipping()
    {
        /*
            if (!$this->getSectionConfigData('checkout_shipping_tablerate/active')) {
                return;
            }
        */

        $address = $this->_quote->getShippingAddress();
        $countries = $this->getTableRateCountries();
        $rates = array();

        foreach ($countries as $country) {
            if ($country == '0') { // *, All countries
                // Can't query on 0, so set to non-existing country
                $country = 'ALL';
            }
            $address->setCountryId($country);
            $address->setCollectShippingRates(true)->collectShippingRates();

            // Get shipping rate by code (getShippingRateByCode doesn't check on isDeleted(), getAllShippingRates() does)
            $rate = null;
            $allRates = $address->getAllShippingRates();
            foreach ($allRates as $r) {
                if ($r->getCode() == 'tablerate_bestway') {
                    $rate = $r;
                    break;
                }
            }

            if ($rate === null) {
                continue;
            }

            if ($rate instanceof Mage_Shipping_Model_Rate_Result_Error) {
                continue;
            }

            // Todo add function to enable disable tax for the rate shipping method to avoid problems when merchant uses prices including the tax

            $rates[] = array(
                'country' => $country,
                'price' => $rate->getPrice(), //'price'   => (float) Mage::helper('tax')->getShippingPrice($rate->getPrice(), false, false), test met optie voor verzendmethode btw aan of uit
                'code' => $rate->getCode(),
                'method' => $rate->getMethodTitle(),
                'carrier' => $rate->getCarrierTitle(),
            );
        }

        foreach ($rates as $rate) {
            $title = $rate['carrier'] . ' - ' . $rate['method'];
            $shipping = new MspFlatRateShipping($title, $rate['price']);

            $filter = new MspShippingFilters();
            if ($rate['country'] != 'ALL') {
                $filter->AddAllowedPostalArea($rate['country']);
                $shipping->AddShippingRestrictions($filter);
            } else {
                // Wildcard country, exclude all countries we already have a rate for
                foreach ($countries as $country) {
                    if ($country != '0') {
                        $filter->AddExcludedPostalArea($country);
                    }
                }
                $shipping->AddShippingRestrictions($filter);
            }
            $this->api->cart->AddShipping($shipping);
        }
    }

    protected function setTaxes()
    {
        $this->_getTaxTable($this->_getShippingTaxRules(), 'default');
        $this->_getTaxTable($this->_getTaxRules(), 'alternate');
        // Add 'none' group?
    }

    protected function _getTaxTable($rules, $type)
    {
        if (is_array($rules)) {
            foreach ($rules as $group => $taxRates) {
                if ($type != 'default') {
                    $table = new MspAlternateTaxTable($group, 'true');
                    $shippingTaxed = 'false';
                } else {
                    $shippingTaxed = 'true';
                }

                if (is_array($taxRates)) {
                    foreach ($taxRates as $rate) {
                        if ($type != 'default') {
                            $rule = new MspAlternateTaxRule($rate['value']);
                            $rule->AddPostalArea($rate['country']);
                            $table->AddAlternateTaxRules($rule);
                        } else {
                            $rule = new MspDefaultTaxRule($rate['value'], $shippingTaxed);
                            $rule->AddPostalArea($rate['country']);
                            $this->api->cart->AddDefaultTaxRules($rule);
                        }
                    }
                } else {
                    $taxRate = $taxRates / 100;
                    if ($type != 'default') {
                        $rule = new MspAlternateTaxRule($taxRate);
                        $rule->SetWorldArea();
                        $table->AddAlternateTaxRules($rule);
                    } else {
                        $rule = new MspDefaultTaxRule($taxRate, $shippingTaxed);
                        $rule->SetWorldArea();
                        $this->api->cart->AddDefaultTaxRules($rule);
                    }
                }
                if ($type != 'default') {
                    $this->api->cart->AddAlternateTaxTables($table);
                }
            }
        } else {
            if (is_numeric($rules)) {
                $taxRate = $rules / 100;
                if ($type != 'default') {
                    $table = new MspAlternateTaxTable();
                    $rule = new MspAlternateTaxRule($taxRate);
                    $rule->SetWorldArea();
                    $table->AddAlternateTaxRules($rule);
                    $this->api->cart->AddAlternateTaxTables($table);
                } else {
                    $rule = new MspDefaultTaxRule($taxRate, 'true');
                    $rule->SetWorldArea();
                    $this->api->cart->AddDefaultTaxRules($rule);
                }
            }
        }
    }

    protected function _getTaxRules()
    {
        $customerTaxClass = $this->_getCustomerTaxClass();
        if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
            $request = Mage::getSingleton('tax/calculation')->getRateRequest();

            return Mage::getSingleton('tax/calculation')->getRatesForAllProductTaxClasses($request->setCustomerClassId($customerTaxClass));
        } else {
            $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerTaxClass($customerTaxClass);
            $rules = array();
            foreach ($customerRules as $rule) {
                $rules[$rule['product_class']][] = $rule;
            }

            return $rules;
        }
    }

    protected function _getShippingTaxRules()
    {
        $customerTaxClass = $this->_getCustomerTaxClass();
        if ($shippingTaxClass = Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, $this->_quote->getStoreId())) {
            if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
                $request = Mage::getSingleton('tax/calculation')->getRateRequest();
                $request->setCustomerClassId($customerTaxClass)->setProductClassId($shippingTaxClass);

                return Mage::getSingleton('tax/calculation')->getRate($request);
            }
            $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerAndProductTaxClasses($customerTaxClass, $shippingTaxClass);
            $rules = array();
            foreach ($customerRules as $rule) {
                $rules[$rule['product_class']][] = $rule;
            }
            return $rules;
        }

        return array();
    }

    protected function _getCustomerTaxClass()
    {
        $customerGroup = $this->_quote->getCustomerGroupId();
        if (!$customerGroup) {
            $customerGroup = Mage::getStoreConfig('customer/create_account/default_group', $this->_quote->getStoreId());
        }

        return Mage::getModel('customer/group')->load($customerGroup)->getTaxClassId();
    }

    protected function _createQwindoOrder($data, $response)
    {
        // We randomly sleep the callback to avoid duplicate orders on callbacks processed at the same time
        sleep(rand(1, 10));

        if (!file_exists(Mage::getBaseDir('log') . $data['transaction_id'] . '.log')) {
            Mage::log($data['transaction_id'], null, $data['transaction_id'] . '.log', true);

            $orders = Mage::getModel('sales/order')->getCollection()->addAttributeToFilter('ext_order_id', $data['transaction_id']);

            if (count($orders)) {
                $this->getBase()->log("Existing order found (%d), canceling create order", count($orders));
                return;
            }

            try {
                /*
                 * START NEW ORDER CREATED CODE
                 */
                $websiteId = Mage::app()->getWebsite()->getId();
                $store = Mage::app()->getStore();
                $store_id = $store->getId();

                $shipping_address = array(
                    'firstname' => $data['delivery']['first_name'],
                    'lastname' => $data['delivery']['last_name'],
                    'street' => array(
                        '0' => $data['delivery']['address1'],
                        '1' => $data['delivery']['house_number'],
                    ),
                    'city' => $data['delivery']['city'],
                    'region_id' => '',
                    'region' => '',
                    'postcode' => $data['delivery']['zip_code'],
                    'country_id' => strtoupper($data['delivery']['country']),
                    'telephone' => $data['delivery']['phone1'],
                );

                $billing_address = array(
                    'firstname' => $data['customer']['first_name'],
                    'lastname' => $data['customer']['last_name'],
                    'street' => array(
                        '0' => $data['customer']['address1'],
                        '1' => $data['customer']['house_number'],
                    ),
                    'city' => $data['customer']['city'],
                    'region_id' => '',
                    'region' => '',
                    'postcode' => $data['customer']['zip_code'],
                    'country_id' => strtoupper($data['customer']['country']),
                    'telephone' => $data['customer']['phone1'],
                );

                $customer = Mage::getModel("customer/customer");
                $customer->website_id = $websiteId;
                $customer->setStore($store);

                // Customer Information
                $firstname = $data['customer']['first_name'];
                $lastname = $data['customer']['last_name'];
                $email = $data['customer']['email'];
                $passwordLength = 10;
                $password = $customer->generatePassword($passwordLength);

                try {
                    $customer->firstname = $firstname;
                    $customer->lastname = $lastname;
                    $customer->email = $email;
                    $customer->password_hash = md5($password);
                    $customer->setPassword($password);

                    if ($customer->save()) {
                        $customAddress = Mage::getModel('customer/address');
                        $customAddress->setData($shipping_address)->setCustomerId($customer->getId())->setIsDefaultBilling('0')->setIsDefaultShipping('1')->setSaveInAddressBook('1');
                        try {
                            $customAddress->save();
                        } catch (Exception $ex) {
                        }

                        $customAddress = Mage::getModel('customer/address');
                        $customAddress->setData($billing_address)->setCustomerId($customer->getId())->setIsDefaultBilling('1')->setIsDefaultShipping('0')->setSaveInAddressBook('1');
                        try {
                            $customAddress->save();
                        } catch (Exception $ex) {
                        }

                        $customerId = $customer->getId();
                        if ($config["send_new_account_email"]) {
                            $customer->sendNewAccountEmail();
                        }
                    } else {
                        $customerId = '0';
                    }
                } catch (Exception $e) {
                    $customer->loadByEmail($email);
                    $customerId = $customer->getId();
                }

                /* ------------------------------------------------------------------------
                  Load Customer
                  ------------------------------------------------------------------------ */
                $customer = Mage::getModel('customer/customer')->load($customerId);

                /* ------------------------------------------------------------------------
                  Payment and Shipping Method
                  ------------------------------------------------------------------------ */
                $payment_method = 'mspcheckout';
                $shipping_method = $data['order_adjustment']['shipping']['flat_rate_shipping']['id'] . '_' . $data['order_adjustment']['shipping']['flat_rate_shipping']['provider'];

                /* ------------------------------------------------------------------------
                  Create a Quote
                  ------------------------------------------------------------------------ */
                $quote = Mage::getModel('sales/quote')->setStoreId($store_id)->load($data['transaction_id'])->setIsActive(true);

                $quote->assignCustomer($customer);
                $quote->setSendConfirmation(0);

                /* ------------------------------------------------------------------------
                  Add products to Quote
                  ------------------------------------------------------------------------ */
                foreach ($data['shopping_cart']['items'] as $item) {
                    $product = Mage::getModel('catalog/product')->load($item['merchant_item_id']);
                    $options = array();
                    $customOption = array();

                    if (isset($item['options']) && !empty($item['options'])) {
                        foreach ($item['options'] as $option) {
                            $parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($product->getId());
                            if (!$parentIds) {
                                $parentIds = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($product->getId());
                            }
                            if (isset($parentIds[0])) {
                                $parent = Mage::getModel('catalog/product')->load($parentIds[0]);
                            } else {
                                $parent = $product;
                            }

                            if ($parent->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
                                $paramsSuperAttribute = array('super_attribute' => array());
                                foreach ($parent->getTypeInstance(true)->getConfigurableAttributes($parent) as $attribute) {
                                    $options[$attribute->getProductAttribute()->getAttributeId()] = (int) $product->getData($attribute->getProductAttribute()->getAttributeCode());
                                }
                            }

                            // Set custom options
                            foreach ($parent->getOptions() as $value) {
                                if (is_object($value)) {
                                    $optionobjects = $value->getValues();
                                    $values = array();
                                    foreach ($optionobjects as $options2) {
                                        $data_option = $options2->getData();

                                        if ($data_option['option_id'] == $option['set_id']) {
                                            $customOption[$option['set_id']] = $option['id'];
                                        }
                                    }
                                }
                            }
                        }
                        $productInfo = array(
                            'qty' => $item['quantity'],
                            'product' => $item['merchant_item_id'],
                            'super_attribute' => $options,
                            'options' => $customOption
                        );

                        // Assign products with options
                        $quote->addProduct($parent, new Varien_Object($productInfo));
                    } else {
                        $productInfo = array(
                            'qty' => $item['quantity'],
                            'product' => $item['merchant_item_id']
                        );

                        // Assign products with options
                        $quote->addProduct($product, new Varien_Object($productInfo));
                    }
                }

                /* ------------------------------------------------------------------------
                  Assign Address, Shipping and Payment methods
                  ------------------------------------------------------------------------ */
                $billingAddress = $quote->getBillingAddress()->addData($billing_address);
                $shippingAddress = $quote->getShippingAddress()->addData($shipping_address);

                $shippingAddress->setCollectShippingRates(true)
                        ->setShippingMethod($shipping_method)
                        ->setPaymentMethod($payment_method);

                $shippingAddress->collectShippingRates();
                $shippingAddress->setCollectShippingRates(true)
                        ->setShippingMethod($shipping_method)
                        ->setPaymentMethod($payment_method);

                $quote->getPayment()->importData(array('method' => $payment_method));

                $quote->collectTotals()->save();

                /* ------------------------------------------------------------------------
                  SECTION : CHECKOUT
                  ------------------------------------------------------------------------ */
                $convertQuote = Mage::getModel('sales/convert_quote');

                if ($quote->getIsVirtual()) {
                    $order = $convertQuote->addressToOrder($quote->getBillingAddress());
                } else {
                    $order = $convertQuote->addressToOrder($quote->getShippingAddress());
                }

                $order->setExtOrderId($data['transaction_id']);
                $order->setExtCustomerId($customerId);

                // Assign payment method
                $quotePayment = $quote->getPayment();

                $quotePayment->setMethod($quote->getPayment()->getMethod());

                $quote->setPayment($quotePayment);

                $orderPayment = $convertQuote->paymentToOrderPayment($quotePayment);

                $order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
                $order->setPayment($convertQuote->paymentToOrderPayment($quote->getPayment()));

                if (!$quote->getIsVirtual()) {
                    $order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
                }

                // Set payment options
                $order->setPayment($convertQuote->paymentToOrderPayment($quote->getPayment()));

                // Order products
                $items = $quote->getAllItems();

                foreach ($items as $item) {
                    // @var $item Mage_Sales_Model_Quote_Item
                    $orderItem = $convertQuote->itemToOrderItem($item);

                    if ($item->getParentItem()) {
                        $orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId()));
                    }

                    $order->addItem($orderItem);
                }

                $new_status = $this->getSectionConfigData("settings/order_status");

                $customFieldData = '';
                if (!empty($data['custom_fields'])) {
                    $customFieldData .= Mage::helper("msp")->__("<br/><br/><strong>Custom field data:</strong><br/>");

                    foreach ($data['custom_fields'] as $name => $value) {
                        $customFieldData .= $name . ': ' . $value . '<br/>';
                    }
                }

                $order->addStatusToHistory($new_status, Mage::helper("msp")->__("Qwindo order created") . '<br/>' . Mage::helper("msp")->__("Quote ID: <strong>%s</strong>", $data['transaction_id']) . $customFieldData);

                // Update stock
                Mage::dispatchEvent('sales_model_service_quote_submit_before', array('order' => $order, 'quote' => $quote));

                $order->setCanShipPartiallyItem(false);
                $order->place();
                $order->save();
                $order->setEmailSent(false);
                $order->sendNewOrderEmail();
                $order->setEmailSent(true);
                $order->save();
                $quote->setIsActive(0);
                $quote->save();
                /*
                 * END NEW ORDER CREATEON CODE
                 */
            } catch (Exception $e) {
                $error = '{
	                    "success": false,
	                    "data": {
	                        "error_code": "QW-10002",
	                        "error": "Could not create or update the order:' . $e->getMessage() . '"
	                        }
	                    }'
                ;
                Mage::log($error, null, 'Order creation failed ' . $data['transaction_id'] . '.log', true);
                Mage::app()->getResponse()->setHeader('HTTP/1.0', 500, true);
                Mage::app()->getResponse()->setHttpResponseCode(500);
                Mage::app()->getResponse()->setBody($error);
                return;
            }
        }
    }

    protected function _createOrder($quoteId)
    {
        $this->getBase()->log("Creating order");

        $api = $this->api;

        // Check if an order is already created
        $orders = Mage::getModel('sales/order')->getCollection()->addAttributeToFilter('ext_order_id', $quoteId);

        if (count($orders)) {
            $this->getBase()->log("Existing order found (%d), canceling create order", count($orders));
            return;
        }

        $storeId = Mage::app()->getStore()->getId();
        $config = Mage::getStoreConfig('mspcheckout' . "/settings", $storeId);

        // Load quote
        $this->getBase()->log("Loading quote");
        $quote = Mage::getModel('sales/quote')->setStoreId($storeId)->load($quoteId)->setIsActive(true);

        // Load details
        $this->getBase()->log("Loading details");
        $billing = $this->_importAddress($api->details['customer']);

        if (isset($api->details['custom-fields']['company'])) {
            $billing->setCompany($api->details['custom-fields']['company']);
        }

        $quote->getPayment()->importData(array('method' => 'mspcheckout'));
        $this->_importTotals($quote->getShippingAddress());

        // Addresses that we use when creating the new customer account
        $shipping_address = array(
            'firstname' => $this->_getArrayValue($api->details, 'customer-delivery', 'firstname'),
            'lastname' => $this->_getArrayValue($api->details, 'customer-delivery', 'lastname'),
            'street' => array(
                '0' => $this->_getArrayValue($api->details, 'customer-delivery', 'address1'),
                '1' => $this->_getArrayValue($api->details, 'customer-delivery', 'housenumber'),
            ),
            'city' => $this->_getArrayValue($api->details, 'customer-delivery', 'city'),
            'region_id' => '',
            'region' => '',
            'postcode' => $this->_getArrayValue($api->details, 'customer-delivery', 'zipcode'),
            'country_id' => $this->_getArrayValue($api->details, 'customer-delivery', 'country'), /* Croatia */
            'telephone' => $this->_getArrayValue($api->details, 'customer-delivery', 'phone1'),
        );

        $billing_address = array(
            'firstname' => $api->details['customer']['firstname'],
            'lastname' => $api->details['customer']['lastname'],
            'street' => array(
                '0' => $api->details['customer']['address1'],
                '1' => $api->details['customer']['housenumber'],
            ),
            'city' => $api->details['customer']['city'],
            'region_id' => '',
            'region' => '',
            'postcode' => $api->details['customer']['zipcode'],
            'country_id' => $api->details['customer']['country'],
            'telephone' => $api->details['customer']['phone1'],
        );

        /**
         * Start adding customer code
         */
        // Website and Store details
        $websiteId = Mage::app()->getWebsite()->getId();
        $store = Mage::app()->getStore();

        $customer = Mage::getModel("customer/customer");
        $customer->website_id = $websiteId;
        $customer->setStore($store);

        // Customer Information
        $firstname = $api->details['customer']['firstname'];
        $lastname = $api->details['customer']['lastname'];
        $email = $api->details['customer']['email'];
        $passwordLength = 10;
        $password = $customer->generatePassword($passwordLength);

        try {
            $customer->firstname = $firstname;
            $customer->lastname = $lastname;
            $customer->email = $email;
            $customer->password_hash = md5($password);
            $customer->setPassword($password);

            if ($customer->save()) {
                $customAddress = Mage::getModel('customer/address');
                $customAddress->setData($shipping_address)->setCustomerId($customer->getId())->setIsDefaultBilling('0')->setIsDefaultShipping('1')->setSaveInAddressBook('1');
                try {
                    $customAddress->save();
                } catch (Exception $ex) {
                }

                $customAddress = Mage::getModel('customer/address');
                $customAddress->setData($billing_address)->setCustomerId($customer->getId())->setIsDefaultBilling('1')->setIsDefaultShipping('0')->setSaveInAddressBook('1');
                try {
                    $customAddress->save();
                } catch (Exception $ex) {
                }

                $customerId = $customer->getId();

                if ($config["send_new_account_email"]) {
                    $customer->sendNewAccountEmail();
                }
            } else {
                $customerId = '0';
            }
        } catch (Exception $e) {
            $customer->loadByEmail($email);
            $customerId = $customer->getId();
        }

        $customerObj = Mage::getModel('customer/customer')->load($customerId);
        $quote->assignCustomer($customerObj);
        // We add the customer to quote that will be converted to an order later, but because the customer could exist
        // already then the addresses that are used are wrong. We need to update the addresses within the quote with
        // the addresses used at FCO, so set the billing and shipping addresses again
        $quote->setBillingAddress($billing);
        $customerDelivery = isset($api->details['customer-delivery']) ? $api->details['customer-delivery'] : array();
        $shipping = $this->_importAddress($customerDelivery);
        $quote->setShippingAddress($shipping);
        // Finished resetting the addresses

        /**
         * End adding customer code
         */
        // Create order
        $this->getBase()->log("Create order");
        $convertQuote = Mage::getSingleton('sales/convert_quote');

        $order = $convertQuote->toOrder($quote);
        $order->setQuote($quote);
        if ($quote->isVirtual()) {
            $convertQuote->addressToOrder($quote->getBillingAddress(), $order);
        } else {
            $convertQuote->addressToOrder($quote->getShippingAddress(), $order);
        }

        $order->setExtOrderId($quoteId);
        $order->setExtCustomerId($customerId);

        if (!$order->getCustomerEmail()) {
            $order->setCustomerEmail($billing->getEmail())
                    ->setCustomerPrefix($billing->getPrefix())
                    ->setCustomerFirstname($billing->getFirstname())
                    ->setCustomerMiddlename($billing->getMiddlename())
                    ->setCustomerLastname($billing->getLastname())
                    ->setCustomerSuffix($billing->getSuffix());
        }

        $order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
        if (!$quote->isVirtual()) {
            $order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
        }

        foreach ($quote->getAllItems() as $item) {
            $orderItem = $convertQuote->itemToOrderItem($item);
            if ($item->getParentItem()) {
                $orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId()));
            }
            $order->addItem($orderItem);
        }

        $payment = Mage::getModel('sales/order_payment')->setMethod('mspcheckout');
        $order->setPayment($payment);
        $order->setCanShipPartiallyItem(false);

        $new_status = $this->getSectionConfigData("settings/order_status");

        $customFieldData = '';
        if (!empty($api->details['custom-fields'])) {
            $customFieldData .= Mage::helper("msp")->__("<br/><br/><strong>Custom field data:</strong><br/>");

            foreach ($api->details['custom-fields'] as $name => $value) {
                $customFieldData .= $name . ': ' . $value . '<br/>';
            }
        }

        $order->addStatusToHistory($new_status, Mage::helper("msp")->__("Order created") . '<br/>' . Mage::helper("msp")->__("Quote ID: <strong>%s</strong>", $quoteId) . $customFieldData);

        $this->getBase()->log("Placing and saving order");

        // Update stock
        Mage::dispatchEvent('sales_model_service_quote_submit_before', array('order' => $order, 'quote' => $quote));

        $order->place();
        $order->save();
        $this->getBase()->log("Sending order e-mail");
        $order->sendNewOrderEmail();
    }

    protected function _importAddress($values, Varien_Object $qAddress = null)
    {
        if (is_array($values)) {
            $values = new Varien_Object($values);
        }

        if (!$qAddress) {
            $qAddress = Mage::getModel('sales/quote_address');
        }

        $qAddress->setFirstname($values->firstname)->setLastname($values->lastname);

        //$region = Mage::getModel('directory/region')->loadByCode('', $values->country);

        $qAddress->setCompany($values->company)
                ->setEmail($values->email)
                ->setStreet(trim($values->address1 . ' ' . $values->housenumber . "\n" . $values->address2))
                ->setCity($values->city)
                //->setRegion($values->state)
                //->setRegionId($region->getId())
                ->setPostcode($values->zipcode)
                ->setCountryId($values->country)
                ->setTelephone($values->phone1)
                ->setFax($values->phone2);

        return $qAddress;
    }

    protected function _importQwindoAddress($values, Varien_Object $qAddress = null)
    {
        if (is_array($values)) {
            $values = new Varien_Object($values);
        }

        if (!$qAddress) {
            $qAddress = Mage::getModel('sales/quote_address');
        }

        $qAddress->setFirstname($values->first_name)->setLastname($values->last_name);

        //$region = Mage::getModel('directory/region')->loadByCode('', $values->country);

        $qAddress->setCompany($values->company)
                ->setEmail($values->email)
                ->setStreet(trim($values->address1 . ' ' . $values->house_number . "\n" . $values->address2))
                ->setCity($values->city)
                //->setRegion($values->state)
                //->setRegionId($region->getId())
                ->setPostcode($values->zip_code)
                ->setCountryId(strtoupper($values->country))
                ->setTelephone($values->phone1)
                ->setFax($values->phone2);

        return $qAddress;
    }

    protected function _getShippingInfos($storeId = null)
    {
        $cacheKey = ($storeId === null) ? 'nofilter' : $storeId;
        if (!isset($this->_cachedShippingInfo[$cacheKey])) {
            /* @var $shipping Mage_Shipping_Model_Shipping */
            $shipping = Mage::getModel('shipping/shipping');
            $carriers = Mage::getStoreConfig('carriers', $storeId);
            $infos = array();

            foreach (array_keys($carriers) as $carrierCode) {
                $carrier = $shipping->getCarrierByCode($carrierCode);
                if (!$carrier) {
                    continue;
                }

                if ($carrierCode == 'googlecheckout') {
                    // Add info about internal google checkout methods
                    $methods = array_merge($carrier->getAllowedMethods(), $carrier->getInternallyAllowedMethods());
                    $carrierName = 'Google Checkout';
                } else {
                    $methods = $carrier->getAllowedMethods();
                    $carrierName = Mage::getStoreConfig('carriers/' . $carrierCode . '/title', $storeId);
                }

                foreach ($methods as $methodCode => $methodName) {
                    $code = $carrierCode . '_' . $methodCode;
                    $name = sprintf('%s - %s', $carrierName, $methodName);
                    $infos[$code] = array(
                        'code' => $code,
                        'name' => $name, // Internal name for google checkout api - to distinguish it in google requests
                        'carrier' => $carrierCode,
                        'carrier_title' => $carrierName,
                        'method' => $methodCode,
                        'method_title' => $methodName
                    );
                }
            }
            $this->_cachedShippingInfo[$cacheKey] = $infos;
        }

        return $this->_cachedShippingInfo[$cacheKey];
    }

    protected function _createShippingRate($code, $storeId = null)
    {
        $rate = Mage::getModel('sales/quote_address_rate')->setCode($code);

        $infos = $this->_getShippingInfos($storeId);
        if (isset($infos[$code])) {
            $info = $infos[$code];
            $rate->setCarrier($info['carrier'])->setCarrierTitle($info['carrier_title'])->setMethod($info['method'])->setMethodTitle($info['method_title']);
        }

        return $rate;
    }

    protected function _importTotals($qAddress)
    {
        $details = $this->api->details;

        $qAddress->setTaxAmount($this->_reCalculateToStoreCurrency($details['total-tax']['total'], $qAddress->getQuote()));
        $qAddress->setBaseTaxAmount($details['total-tax']['total']);

        if ($details['shipping']['type'] == 'flat-rate-shipping') {
            $method = 'mspcheckout_flatrate';
        } elseif ($details['shipping']['type'] == 'pickup') {
            $method = 'mspcheckout_pickup';
        }

        if (!empty($method)) {
            // Mage::getSingleton('tax/config')->setShippingPriceIncludeTax(false);

            $excludingTax = $details['shipping']['cost'];

            $qAddress->setShippingMethod($method)
                    ->setShippingDescription($details['shipping']['name'])
                    ->setShippingAmount($this->_reCalculateToStoreCurrency($excludingTax, $qAddress->getQuote()), true)
                    ->setBaseShippingAmount($excludingTax, true);

            $includingTax = Mage::helper('tax')->getShippingPrice($excludingTax, true, $qAddress, $qAddress->getQuote()->getCustomerTaxClassId());
            $shippingTax = $includingTax - $excludingTax;
            $qAddress->setShippingTaxAmount($this->_reCalculateToStoreCurrency($shippingTax, $qAddress->getQuote()))
                    ->setBaseShippingTaxAmount($shippingTax)
                    ->setShippingInclTax($includingTax)
                    ->setBaseShippingInclTax($this->_reCalculateToStoreCurrency($includingTax, $qAddress->getQuote()));
        } else {
            $qAddress->setShippingMethod(null);
        }

        $qAddress->setGrandTotal($this->_reCalculateToStoreCurrency($details['order-total']['total'], $qAddress->getQuote()));
        $qAddress->setBaseGrandTotal($details['order-total']['total']);
    }

    protected function _reCalculateToStoreCurrency($amount, $quote)
    {
        if ($quote->getQuoteCurrencyCode() != $quote->getBaseCurrencyCode()) {
            $amount = $amount * $quote->getStoreToQuoteRate();
        }

        return $amount;
    }

    public function getConfigData($field, $storeId = null)
    {
        if ($field == 'title') {
            return 'MultiSafepay fast checkout';
        }

        if (null === $storeId) {
            if ($this->_storeId !== null) {
                $storeId = $this->_storeId;
            } else {
                $storeId = $this->getStore();
            }
        }
        $path = $this->_settings . "/settings/" . $field;

        return Mage::getStoreConfig($path, $storeId);
    }

    public function getSectionConfigData($field, $storeId = null)
    {
        if (null === $storeId) {
            if ($this->_storeId !== null) {
                $storeId = $this->_storeId;
            } else {
                $storeId = $this->getStore();
            }
        }
        $path = $this->_settings . "/" . $field;

        return Mage::getStoreConfig($path, $storeId);
    }

    // Get shipping methods for given parameters
    // Result as an array:
    // 'name' => 'test-name'
    // 'cost' => '123'
    // 'currency' => 'EUR' (currently only this supported)
    public function getShippingMethodsFiltered($country, $countryCode, $weight = '', $size = '', $transactionId)
    {
        $out = array();

        // Pickup
        if ($this->getSectionConfigData('checkout_shipping_pickup/active')) {
            $title = $this->getSectionConfigData('checkout_shipping_pickup/title');
            $price = $this->getSectionConfigData('checkout_shipping_pickup/price');
            $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);

            $shipping = array();
            $shipping['name'] = $title;
            $shipping['cost'] = $price;
            $shipping['currency'] = 'EUR';
            $out[] = $shipping;
        }

        // Flat rate
        if ($this->getSectionConfigData('checkout_shipping_flatrate/active')) {
            for ($i = 1; $i <= 3; $i++) {
                $allowSpecific = $this->getSectionConfigData('checkout_shipping_flatrate/sallowspecific_' . $i);
                // Only specific countries?
                if ($allowSpecific) {
                    $specificCountries = $this->getSectionConfigData('checkout_shipping_flatrate/specificcountry_' . $i);
                    // Is our countryCode in selected specific allowed countries?
                    if (stristr($specificCountries, $countryCode) == false) {
                        continue; // No - skip to another method
                    }
                }

                $title = $this->getSectionConfigData('checkout_shipping_flatrate/title_' . $i);
                $price = $this->getSectionConfigData('checkout_shipping_flatrate/price_' . $i);
                $price = number_format($price, 2, '.', '');
                $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);

                if (empty($title) || $price <= 0) { // Do not include invalid entries
                    continue;
                }

                $shipping = array();
                $shipping['name'] = $title;
                $shipping['cost'] = $price;
                $shipping['currency'] = 'EUR';
                $out[] = $shipping;
            }
        }

        return $out;
    }

    public function getShippingRatesFiltered($transactionId, $countryCode, $zipCode, $settings)
    {
        $output = array();

        /** @var $quote Mage_Sales_Model_Quote */
        $quote = Mage::getModel('sales/quote')->load($transactionId);

        /** @var $shippingAddress Mage_Sales_Model_Quote_Address */
        $shippingAddress = $quote->getShippingAddress();
        $shippingAddress->setCountryId($countryCode);
        $shippingAddress->setPostcode($zipCode);
        $shippingAddress->collectTotals();
        $shippingAddress->setCollectShippingRates(true);

        $rates = $shippingAddress->collectShippingRates()->getGroupedAllShippingRates();

        foreach ($rates as $carrier) {
            foreach ($carrier as $rate) {
                if ($rate->getCode() == 'tablerate_bestway') {
                    $tablerateColl = Mage::getResourceModel('shipping/carrier_tablerate_collection');
                    $shipping = array();
                    foreach ($tablerateColl as $tablerate) {
                        $ratedata = $tablerate->getData();
                        $cost = (double) $_GET['amount'];
                        $amount = $cost / 100;

                        if ($ratedata['condition_value'] <= $amount && $_GET['countrycode'] == $ratedata['dest_country_id']) {
                            $shipping['id'] = $rate->getCode();
                            $shipping['name'] = $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle();
                            $shipping['cost'] = number_format($ratedata['price'], 2, '.', '');
                            $shipping['currency'] = $quote->getQuoteCurrencyCode();
                        }
                    }
                    $output[] = $shipping;
                } else {
                    $shipping = array();
                    $shipping['id'] = $rate->getCode();
                    $shipping['name'] = $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle();
                    $shipping['cost'] = number_format($rate->getPrice(), 2, '.', '');
                    $shipping['currency'] = $quote->getQuoteCurrencyCode();

                    $output[] = $shipping;
                }
            }
        }

        if ($this->getSectionConfigData('checkout_custom_fields/fco_postnl')) {
            $shipping = array();
            $shipping['id'] = 'PostNL';
            $shipping['name'] = 'Post NL - Pak je gemak';
            $shipping['cost'] = number_format($this->getSectionConfigData('checkout_custom_fields/fco_postnl_amount'), 2, '.', '');
            $shipping['currency'] = 'EUR';

            $output[] = $shipping;
        }

        return $output;
    }

    public function getShippingMethodsFilteredXML($country, $countryCode, $weight = '', $size = '', $transactionId)
    {
        $methods = $this->getShippingMethodsFiltered($country, $countryCode, $weight, $size, $transactionId);

        $outxml = '<shipping-info>';
        foreach ($methods as $method) {
            $outxml .= '<shipping>';
            $outxml .= '<shipping-name>';
            $outxml .= htmlentities($method['name']);
            $outxml .= '</shipping-name>';
            $outxml .= '<shipping-cost currency="' . $method['currency'] . '">';
            $outxml .= $method['cost'];
            $outxml .= '</shipping-cost>';
            $outxml .= '</shipping>';
        }
        $outxml .= '</shipping-info>';

        return $outxml;
    }

    /**
     * @param $transactionId integer
     * @param $countryCode   string
     * @param $postCode      string
     * @param $settings      array
     * @return string
     */
    public function getShippingRatesFilteredXML($transactionId, $countryCode, $zipCode, $settings)
    {
        $rates = $this->getShippingRatesFiltered($transactionId, $countryCode, $zipCode, $settings);

        $outxml = '<?xml version="1.0" encoding="UTF-8"?>';
        $outxml .= '<shipping-info>';
        foreach ($rates as $rate) {
            if (!empty($rate)) {
                $outxml .= '<shipping>';
                $outxml .= '<shipping-name>' . htmlentities($rate['name']) . '</shipping-name>';
                $outxml .= '<shipping-cost currency="' . $rate['currency'] . '">' . $rate['cost'] . '</shipping-cost>';
                $outxml .= '<shipping-id>' . $rate['id'] . '</shipping-id>';
                $outxml .= '</shipping>';
            }
        }
        $outxml .= '</shipping-info>';

        return $outxml;
    }

    /**
     * @param $array array
     * @param $key1  string
     * @param $key2  string
     * @return string
     */
    protected function _getArrayValue($array, $key1, $key2)
    {
        if (isset($array[$key1])) {
            if (isset($array[$key1][$key2])) {
                return $array[$key1][$key2];
            }
        }

        return '';
    }
}
