<?php
/**
 * RatingApi
 * PHP version 5
 *
 * @category Class
 * @package  UPS\Rating
 * @author   Swagger Codegen team
 * @link     https://github.com/swagger-api/swagger-codegen
 */

/**
 * Rate
 *
 * The Rating API is used when rating or shopping a shipment. # Reference - <a href=\"https://developer.ups.com/api/reference/rating/business-rules\" target=\"_blank\" rel=\"noopener\">Business Rules</a> - <a href=\"https://developer.ups.com/api/reference/rating/appendix\" target=\"_blank\" rel=\"noopener\">Appendix</a> - <a href=\"https://developer.ups.com/api/reference/rating/error-codes\" target=\"_blank\" rel=\"noopener\">Errors</a> - <a href=\"https://developer.ups.com/api/reference/rating/faq\" target=\"_blank\" rel=\"noopener\">FAQ</a> - <a href=\"https://developer.ups.com/api/reference/rating/best-practices\" target=\"_blank\" rel=\"noopener noreferrer\"> Best Practices</a>  <br/><p>Try out UPS APIs with example requests using Postman. Explore API documentation and sample applications through GitHub.</p>  <a href=\"https://god.gw.postman.com/run-collection/29542085-ac21ef26-eecf-4841-b0b2-737d615b6809?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D29542085-ac21ef26-eecf-4841-b0b2-737d615b6809%26entityType%3Dcollection%26workspaceId%3D7e7595f0-4829-4f9a-aee1-75c126b9d417\" target=\"_blank\" rel=\"noopener noreferrer\">   <img src=\"https://run.pstmn.io/button.svg\" alt=\"Run In Postman\" style=\"width: 128px; height: 32px;\"></a> <a href=\"https://github.com/UPS-API\" target=\"_blank\" rel=\"noopener noreferrer\">   <img src=\"https://www.ups.com/assets/resources/webcontent/images/gitHubButton.svg\" alt=\"Open in GitHub\" style=\"width: 128px; height: 32px;\"> </a>
 *
 * 
 * 
 * Generated by: https://github.com/swagger-api/swagger-codegen.git
 * Swagger Codegen version: 3.0.71
 */
/**
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen
 * Do not edit the class manually.
 */

namespace UPS\Rating\Request;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\RequestOptions;
use UPS\Rating\ApiException;
use UPS\Rating\Configuration;
use UPS\Rating\HeaderSelector;
use UPS\Rating\ObjectSerializer;

/**
 * RatingApi Class Doc Comment
 *
 * @category Class
 * @package  UPS\Rating
 * @author   Swagger Codegen team
 * @link     https://github.com/swagger-api/swagger-codegen
 */
class RatingApi
{
    /**
     * @var ClientInterface
     */
    protected $client;

    /**
     * @var Configuration
     */
    protected $config;

    /**
     * @var HeaderSelector
     */
    protected $headerSelector;

    /**
     * @param ClientInterface $client
     * @param Configuration   $config
     * @param HeaderSelector  $selector
     */
    public function __construct(
        ClientInterface $client = null,
        Configuration $config = null,
        HeaderSelector $selector = null
    ) {
        $this->client = $client ?: new Client();
        $this->config = $config ?: new Configuration();
        $this->headerSelector = $selector ?: new HeaderSelector();
    }

    /**
     * @return Configuration
     */
    public function getConfig()
    {
        return $this->config;
    }

    /**
     * Operation deprecatedRate
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $deprecated_version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v1 - v1601 - v1607 - 1701 - 1707 - v2108 - v2205 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \UPS\Rating\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \UPS\Rating\Rating\RATEResponseWrapper
     */
    public function deprecatedRate($body, $deprecated_version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        list($response) = $this->deprecatedRateWithHttpInfo($body, $deprecated_version, $requestoption, $trans_id, $transaction_src, $additionalinfo);
        return $response;
    }

    /**
     * Operation deprecatedRateWithHttpInfo
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $deprecated_version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v1 - v1601 - v1607 - 1701 - 1707 - v2108 - v2205 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \UPS\Rating\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \UPS\Rating\Rating\RATEResponseWrapper, HTTP status code, HTTP response headers (array of strings)
     */
    public function deprecatedRateWithHttpInfo($body, $deprecated_version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        $returnType = '\UPS\Rating\Rating\RATEResponseWrapper';
        $request = $this->deprecatedRateRequest($body, $deprecated_version, $requestoption, $trans_id, $transaction_src, $additionalinfo);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }

            $statusCode = $response->getStatusCode();

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }

            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
                if (!in_array($returnType, ['string','integer','bool'])) {
                    $content = json_decode($content);
                }
            }

            return [
                ObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\RATEResponseWrapper',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 401:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 403:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 429:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation deprecatedRateAsync
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $deprecated_version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v1 - v1601 - v1607 - 1701 - 1707 - v2108 - v2205 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function deprecatedRateAsync($body, $deprecated_version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        return $this->deprecatedRateAsyncWithHttpInfo($body, $deprecated_version, $requestoption, $trans_id, $transaction_src, $additionalinfo)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation deprecatedRateAsyncWithHttpInfo
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $deprecated_version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v1 - v1601 - v1607 - 1701 - 1707 - v2108 - v2205 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function deprecatedRateAsyncWithHttpInfo($body, $deprecated_version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        $returnType = '\UPS\Rating\Rating\RATEResponseWrapper';
        $request = $this->deprecatedRateRequest($body, $deprecated_version, $requestoption, $trans_id, $transaction_src, $additionalinfo);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                        if ($returnType !== 'string') {
                            $content = json_decode($content);
                        }
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deprecatedRate'
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $deprecated_version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v1 - v1601 - v1607 - 1701 - 1707 - v2108 - v2205 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function deprecatedRateRequest($body, $deprecated_version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        // verify the required parameter 'body' is set
        if ($body === null || (is_array($body) && count($body) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $body when calling deprecatedRate'
            );
        }
        // verify the required parameter 'deprecated_version' is set
        if ($deprecated_version === null || (is_array($deprecated_version) && count($deprecated_version) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $deprecated_version when calling deprecatedRate'
            );
        }
        // verify the required parameter 'requestoption' is set
        if ($requestoption === null || (is_array($requestoption) && count($requestoption) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $requestoption when calling deprecatedRate'
            );
        }

        $resourcePath = '/rating/{deprecatedVersion}/{requestoption}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        if ($additionalinfo !== null) {
            $queryParams['additionalinfo'] = ObjectSerializer::toQueryValue($additionalinfo, null);
        }
        // header params
        if ($trans_id !== null) {
            $headerParams['transId'] = ObjectSerializer::toHeaderValue($trans_id);
        }
        // header params
        if ($transaction_src !== null) {
            $headerParams['transactionSrc'] = ObjectSerializer::toHeaderValue($transaction_src);
        }

        // path params
        if ($deprecated_version !== null) {
            $resourcePath = str_replace(
                '{' . 'deprecatedVersion' . '}',
                ObjectSerializer::toPathValue($deprecated_version),
                $resourcePath
            );
        }
        // path params
        if ($requestoption !== null) {
            $resourcePath = str_replace(
                '{' . 'requestoption' . '}',
                ObjectSerializer::toPathValue($requestoption),
                $resourcePath
            );
        }

        // body params
        $_tempBody = null;
        if (isset($body)) {
            $_tempBody = $body;
        }

        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            $httpBody = $_tempBody;
            // \stdClass has no __toString(), so we should encode it manually
            if ($httpBody instanceof \stdClass && $headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($httpBody);
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $multipartContents[] = [
                        'name' => $formParamName,
                        'contents' => $formParamValue
                    ];
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\Query::build($formParams);
            }
        }

        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = \GuzzleHttp\Psr7\Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation rate
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v2409 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \UPS\Rating\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \UPS\Rating\Rating\RATEResponseWrapper
     */
    public function rate($body, $version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        list($response) = $this->rateWithHttpInfo($body, $version, $requestoption, $trans_id, $transaction_src, $additionalinfo);
        return $response;
    }

    /**
     * Operation rateWithHttpInfo
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v2409 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \UPS\Rating\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \UPS\Rating\Rating\RATEResponseWrapper, HTTP status code, HTTP response headers (array of strings)
     */
    public function rateWithHttpInfo($body, $version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        $returnType = '\UPS\Rating\Rating\RATEResponseWrapper';
        $request = $this->rateRequest($body, $version, $requestoption, $trans_id, $transaction_src, $additionalinfo);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }

            $statusCode = $response->getStatusCode();

            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }

            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
                if (!in_array($returnType, ['string','integer','bool'])) {
                    $content = json_decode($content);
                }
            }

            return [
                ObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];

        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\RATEResponseWrapper',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 401:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 403:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 429:
                    $data = ObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\UPS\Rating\Rating\ErrorResponse',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }

    /**
     * Operation rateAsync
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v2409 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function rateAsync($body, $version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        return $this->rateAsyncWithHttpInfo($body, $version, $requestoption, $trans_id, $transaction_src, $additionalinfo)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation rateAsyncWithHttpInfo
     *
     * Rating
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v2409 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function rateAsyncWithHttpInfo($body, $version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        $returnType = '\UPS\Rating\Rating\RATEResponseWrapper';
        $request = $this->rateRequest($body, $version, $requestoption, $trans_id, $transaction_src, $additionalinfo);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                        if ($returnType !== 'string') {
                            $content = json_decode($content);
                        }
                    }

                    return [
                        ObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'rate'
     *
     * @param  \UPS\Rating\Rating\RATERequestWrapper $body Generate sample code for popular API requests by selecting an example below. To view a full sample request and response, first click \&quot;Authorize\&quot; and enter your application credentials, then populate the required parameters above and click \&quot;Try it out\&quot;. (required)
     * @param  string $version Indicates Rate API to display the new release features in Rate API response based on Rate release. See the New section for the latest Rate release.  Valid values: - v2409 (required)
     * @param  string $requestoption Valid Values: - Rate &#x3D; The server rates (The default Request option is Rate if a Request Option is not provided). - Shop &#x3D; The server validates the shipment, and returns rates for all UPS products from the ShipFrom to the ShipTo addresses. - Ratetimeintransit &#x3D; The server rates with transit time information - Shoptimeintransit &#x3D; The server validates the shipment, and returns rates and transit times for all UPS products from the ShipFrom to the ShipTo addresses.  Rate is the only valid request option for UPS Ground Freight Pricing requests. (required)
     * @param  string $trans_id An identifier unique to the request. Length 32 (optional)
     * @param  string $transaction_src An identifier of the client/source application that is making the request.Length 512 (optional, default to testing)
     * @param  string $additionalinfo Valid Values: timeintransit &#x3D; The server rates with transit time information combined with requestoption in URL.Rate is the only valid request option for Ground Freight Pricing requests. Length 15 (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function rateRequest($body, $version, $requestoption, $trans_id = null, $transaction_src = 'testing', $additionalinfo = null)
    {
        // verify the required parameter 'body' is set
        if ($body === null || (is_array($body) && count($body) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $body when calling rate'
            );
        }
        // verify the required parameter 'version' is set
        if ($version === null || (is_array($version) && count($version) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $version when calling rate'
            );
        }
        // verify the required parameter 'requestoption' is set
        if ($requestoption === null || (is_array($requestoption) && count($requestoption) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $requestoption when calling rate'
            );
        }

        $resourcePath = '/rating/{version}/{requestoption}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;

        // query params
        if ($additionalinfo !== null) {
            $queryParams['additionalinfo'] = ObjectSerializer::toQueryValue($additionalinfo, null);
        }
        // header params
        if ($trans_id !== null) {
            $headerParams['transId'] = ObjectSerializer::toHeaderValue($trans_id);
        }
        // header params
        if ($transaction_src !== null) {
            $headerParams['transactionSrc'] = ObjectSerializer::toHeaderValue($transaction_src);
        }

        // path params
        if ($version !== null) {
            $resourcePath = str_replace(
                '{' . 'version' . '}',
                ObjectSerializer::toPathValue($version),
                $resourcePath
            );
        }
        // path params
        if ($requestoption !== null) {
            $resourcePath = str_replace(
                '{' . 'requestoption' . '}',
                ObjectSerializer::toPathValue($requestoption),
                $resourcePath
            );
        }

        // body params
        $_tempBody = null;
        if (isset($body)) {
            $_tempBody = $body;
        }

        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            $httpBody = $_tempBody;
            // \stdClass has no __toString(), so we should encode it manually
            if ($httpBody instanceof \stdClass && $headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($httpBody);
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $multipartContents[] = [
                        'name' => $formParamName,
                        'contents' => $formParamValue
                    ];
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);

            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\Query::build($formParams);
            }
        }

        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }

        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }

        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );

        $query = \GuzzleHttp\Psr7\Query::build($queryParams);
        return new Request(
            'POST',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create http client option
     *
     * @throws \RuntimeException on file opening failure
     * @return array of http client options
     */
    protected function createHttpClientOption()
    {
        $options = [];
        if ($this->config->getDebug()) {
            $options[RequestOptions::DEBUG] = fopen($this->config->getDebugFile(), 'a');
            if (!$options[RequestOptions::DEBUG]) {
                throw new \RuntimeException('Failed to open the debug file: ' . $this->config->getDebugFile());
            }
        }

        return $options;
    }
}
