<?php

namespace RocketShipIt\Carrier;

use RocketShipIt\Request;

/**
 * Core FedEx Class.
 *
 * Used internally to send data, set debug information, change
 * urls, and build xml for FedEx
 */
class Fedex extends \RocketShipIt\Carrier\Base
{
    public $paramSynonyms = [
        'customsOriginCountry' => 'countryOfManufacture',
        'customsHsTariff' => 'harmonizedCode',
        'customsWeightUnit' => 'weightUnit',
        'customsLineAmount' => 'customsValue',
    ];

    public $paramValueSynonyms = [
        'LBS' => 'LB',
        'KGS' => 'KG',
    ];

    public function __construct()
    {
        parent::__construct();
        // Grab the license, username, password for defaults
        $this->key = $this->config->getDefault('fedex', 'key');
        $this->password = $this->config->getDefault('fedex', 'password');
        $this->accountNumber = $this->config->getDefault('fedex', 'accountNumber');
        $this->meterNumber = $this->config->getDefault('fedex', 'meterNumber');

        $this->xmlObject = new \RocketShipIt\Helper\XmlBuilder(true);
        $this->testingUrl = 'https://wsbeta.fedex.com/xml';
        $this->productionUrl = 'https://ws.fedex.com/xml';
        $this->request = new Request();
    }

    // Create the auth xml that is used in every request
    public function access()
    {
        $xml = $this->xmlObject;
        $xml->push('ns:WebAuthenticationDetail');
        $xml->push('ns:UserCredential');
        $xml->element('ns:Key', $this->key);
        $xml->element('ns:Password', $this->password);
        $xml->pop(); // end UserCredential
        $xml->pop(); // end WebAuthenticationDetail
        $xml->push('ns:ClientDetail');
        $xml->element('ns:AccountNumber', $this->accountNumber);
        $xml->element('ns:MeterNumber', $this->meterNumber);
        $xml->pop(); // end ClientDetail

        $this->xmlObject = $xml;

        $this->accessRequest = true;

        return $this->xmlObject->getXml(); // returns xmlstring, but probably not used
    }

    public function request($xml)
    {
        if ($this->mockXmlResponse != '') {
            $this->xmlResponse = $this->getMockResponse();

            return $this->xmlResponse;
        }

        // This function is the only function that actually transmits and receives data
        // from FedEx. All classes use this to send XML to FedEx servers.
        $request = $this->request;
        $this->xmlSent = $xml; // Store the xmlSent for debugging
        $this->xmlResponse = '';
        $request->url = $this->getUrl().'/xml';
        $request->requestTimeout = $this->requestTimeout;
        $request->payload = $xml;
        $request->post();
        if ($request->getError()) {
            $error = $request->getError();
            $xml = "<error>$error</error>";
            $this->xmlResponse = $xml;

            return [$xml];
        }

        // Store curl response for debugging
        $this->curlReturned = $request->getResponse();

        return $this->returnResponseOrDownResponse($request);
    }

    public function getServiceDescriptionFromCode($code)
    {
        $serviceDescriptionMap = [
            'EUROPE_FIRST_INTERNATIONAL_PRIORITY' => 'FedEx Europe First International Priority®',
            'FEDEX_1_DAY_FREIGHT' => 'FedEx 1Day® Freight',
            'FEDEX_2_DAY' => 'FedEx 2Day®',
            'FEDEX_2_DAY_AM' => 'FedEx 2Day® A.M.',
            'FEDEX_2_DAY_FREIGHT' => 'FedEx 2Day® Freight',
            'FEDEX_3_DAY_FREIGHT' => 'FedEx 3Day® Freight',
            'FEDEX_EXPRESS_SAVER' => 'FedEx Express Saver®',
            'FEDEX_FIRST_FREIGHT' => 'FedEx First® Freight',
            'FEDEX_FREIGHT_ECONOMY' => 'FedEx Freight® Economy',
            'FEDEX_FREIGHT_PRIORITY' => 'FedEx Freight® Priority',
            'FEDEX_GROUND' => 'FedEx Ground®',
            'FIRST_OVERNIGHT' => 'FedEx First Overnight®',
            'GROUND_HOME_DELIVERY' => 'FedEx Home Delivery®',
            'INTERNATIONAL_ECONOMY' => 'FedEx International Economy®',
            'INTERNATIONAL_ECONOMY_FREIGHT' => 'FedEx International Economy® Freight',
            'INTERNATIONAL_FIRST' => 'FedEx International First®',
            'INTERNATIONAL_PRIORITY' => 'FedEx International Priority®',
            'INTERNATIONAL_PRIORITY_FREIGHT' => 'FedEx International Priority® Freight',
            'PRIORITY_OVERNIGHT' => 'FedEx Priority Overnight®',
            'SMART_POST' => 'FedEx SmartPost®',
            'STANDARD_OVERNIGHT' => 'FedEx Standard Overnight®',
        ];

        if (isset($serviceDescriptionMap[$code])) {
            return $serviceDescriptionMap[$code];
        }

        return $code;
    }

    // Returns if a country code accepts electronic trade documents,
    // array('inbound' => true/false, 'outbound' => true/false)
    public function acceptsEtd($countryCode)
    {
        return $this->countriesAcceptingEtd[$countryCode];
    }

    public $countriesAcceptingEtd = [
        'AF' => ['inbound' => true, 'outbound' => true],
        'AL' => ['inbound' => true, 'outbound' => false],
        'AW' => ['inbound' => false, 'outbound' => true],
        'AU' => ['inbound' => true, 'outbound' => true],
        'AT' => ['inbound' => true, 'outbound' => true],
        'BS' => ['inbound' => false, 'outbound' => true],
        'BH' => ['inbound' => true, 'outbound' => true],
        'BB' => ['inbound' => true, 'outbound' => true],
        'BD' => ['inbound' => false, 'outbound' => true],
        'BE' => ['inbound' => true, 'outbound' => true],
        'BM' => ['inbound' => true, 'outbound' => true],
        'VG' => ['inbound' => false, 'outbound' => true],
        'CA' => ['inbound' => true, 'outbound' => true],
        'KY' => ['inbound' => false, 'outbound' => true],
        'GB' => ['inbound' => true, 'outbound' => true],
        'CN' => ['inbound' => true, 'outbound' => true],
        'HR' => ['inbound' => true, 'outbound' => false],
        'CY' => ['inbound' => true, 'outbound' => false],
        'CZ' => ['inbound' => true, 'outbound' => true],
        'DK' => ['inbound' => true, 'outbound' => true],
        'GB' => ['inbound' => true, 'outbound' => true],
        'EE' => ['inbound' => true, 'outbound' => false],
        'FI' => ['inbound' => true, 'outbound' => true],
        'FR' => ['inbound' => false, 'outbound' => false],
        'DE' => ['inbound' => true, 'outbound' => false],
        'GU' => ['inbound' => true, 'outbound' => false],
        'GT' => ['inbound' => false, 'outbound' => true],
        'HK' => ['inbound' => true, 'outbound' => true],
        'HU' => ['inbound' => true, 'outbound' => true],
        'IS' => ['inbound' => true, 'outbound' => false],
        'IN' => ['inbound' => true, 'outbound' => false],
        'IE' => ['inbound' => true, 'outbound' => true],
        'IL' => ['inbound' => true, 'outbound' => false],
        'IT' => ['inbound' => true, 'outbound' => false],
        'JP' => ['inbound' => true, 'outbound' => true],
        'JO' => ['inbound' => false, 'outbound' => true],
        'KE' => ['inbound' => false, 'outbound' => true],
        'KR' => ['inbound' => true, 'outbound' => true],
        'KW' => ['inbound' => false, 'outbound' => true],
        'LV' => ['inbound' => true, 'outbound' => false],
        'LI' => ['inbound' => true, 'outbound' => false],
        'LT' => ['inbound' => true, 'outbound' => false],
        'LU' => ['inbound' => true, 'outbound' => true],
        'MO' => ['inbound' => true, 'outbound' => true],
        'MY' => ['inbound' => true, 'outbound' => true],
        'MT' => ['inbound' => false, 'outbound' => true],
        'MH' => ['inbound' => true, 'outbound' => false],
        'MX' => ['inbound' => true, 'outbound' => true],
        'FM' => ['inbound' => true, 'outbound' => false],
        'MC' => ['inbound' => true, 'outbound' => false],
        'NL' => ['inbound' => true, 'outbound' => true],
        'NZ' => ['inbound' => true, 'outbound' => true],
        'GB' => ['inbound' => true, 'outbound' => true],
        'MP' => ['inbound' => true, 'outbound' => false],
        'NO' => ['inbound' => true, 'outbound' => true],
        'OM' => ['inbound' => false, 'outbound' => true],
        'PS' => ['inbound' => true, 'outbound' => false],
        'PW' => ['inbound' => true, 'outbound' => false],
        'PH' => ['inbound' => true, 'outbound' => true],
        'PL' => ['inbound' => true, 'outbound' => false],
        'PT' => ['inbound' => true, 'outbound' => false],
        'PR' => ['inbound' => true, 'outbound' => true],
        'SM' => ['inbound' => true, 'outbound' => false],
        'SA' => ['inbound' => false, 'outbound' => true],
        'GB' => ['inbound' => true, 'outbound' => true],
        'SG' => ['inbound' => true, 'outbound' => true],
        'SK' => ['inbound' => true, 'outbound' => true],
        'SI' => ['inbound' => true, 'outbound' => false],
        'ZA' => ['inbound' => true, 'outbound' => true],
        'ES' => ['inbound' => true, 'outbound' => false],
        'AN' => ['inbound' => false, 'outbound' => true],
        'SE' => ['inbound' => true, 'outbound' => true],
        'CH' => ['inbound' => true, 'outbound' => false],
        'TH' => ['inbound' => true, 'outbound' => true],
        'TW' => ['inbound' => true, 'outbound' => false],
        'TC' => ['inbound' => false, 'outbound' => true],
        'AE' => ['inbound' => false, 'outbound' => true],
        'US' => ['inbound' => true, 'outbound' => true],
        'VI' => ['inbound' => false, 'outbound' => true],
        'IT' => ['inbound' => true, 'outbound' => false],
        'GB' => ['inbound' => true, 'outbound' => true],
    ];
}
