<?php
/**
 * SendEmailApi
 * PHP version 7.2
 *
 * @category Class
 * @package  Infobip
 * @author   Infobip Support
 * @link     https://www.infobip.com
 */

/**
 * Infobip Client API Libraries OpenAPI Specification
 *
 * OpenAPI specification containing public endpoints supported in client API libraries.
 *
 * Contact: support@infobip.com
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * Do not edit the class manually.
 */

namespace Infobip\Api;

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

/**
 * SendEmailApi Class Doc Comment
 *
 * @category Class
 * @package  Infobip
 * @author   Infobip Support
 * @link     https://www.infobip.com
 */
class SendEmailApi
{
    /**
     * @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 getEmailDeliveryReports
     *
     * Email delivery reports
     *
     * @param  string $bulkId Bulk ID for which report is requested. (optional)
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  int $limit Maximum number of reports. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\EmailReportsResult|\Infobip\Model\EmailIgnore1ApiException|\Infobip\Model\EmailIgnore1ApiException
     */
    public function getEmailDeliveryReports($bulkId = null, $messageId = null, $limit = null)
    {
        list($response) = $this->getEmailDeliveryReportsWithHttpInfo($bulkId, $messageId, $limit);
        return $response;
    }

    /**
     * Operation getEmailDeliveryReportsWithHttpInfo
     *
     * Email delivery reports
     *
     * @param  string $bulkId Bulk ID for which report is requested. (optional)
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  int $limit Maximum number of reports. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\EmailReportsResult|\Infobip\Model\EmailIgnore1ApiException|\Infobip\Model\EmailIgnore1ApiException, HTTP status code, HTTP response headers (array of strings)
     */
    public function getEmailDeliveryReportsWithHttpInfo($bulkId = null, $messageId = null, $limit = null)
    {
        $request = $this->getEmailDeliveryReportsRequest($bulkId, $messageId, $limit);

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

    /**
     * Operation getEmailDeliveryReportsAsync
     *
     * Email delivery reports
     *
     * @param  string $bulkId Bulk ID for which report is requested. (optional)
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  int $limit Maximum number of reports. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getEmailDeliveryReportsAsync($bulkId = null, $messageId = null, $limit = null)
    {
        return $this->getEmailDeliveryReportsAsyncWithHttpInfo($bulkId, $messageId, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getEmailDeliveryReportsAsyncWithHttpInfo
     *
     * Email delivery reports
     *
     * @param  string $bulkId Bulk ID for which report is requested. (optional)
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  int $limit Maximum number of reports. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getEmailDeliveryReportsAsyncWithHttpInfo($bulkId = null, $messageId = null, $limit = null)
    {
        $request = $this->getEmailDeliveryReportsRequest($bulkId, $messageId, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getEmailDeliveryReportsResponse($response, $request->getUri());
                },
                function ($exception) {
                    $statusCode = $exception->getCode();
                    $response = $exception->getResponse();
                    $e = new ApiException(
                        "[{$statusCode}] {$exception->getMessage()}",
                        $statusCode,
                        $response ? $response->getHeaders() : null,
                        $response ? (string) $response->getBody() : null
                    );
                    throw $this->getEmailDeliveryReportsApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getEmailDeliveryReports'
     *
     * @param  string $bulkId Bulk ID for which report is requested. (optional)
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  int $limit Maximum number of reports. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getEmailDeliveryReportsRequest($bulkId = null, $messageId = null, $limit = null)
    {
        $resourcePath = '/email/1/reports';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';

        // query params
        if ($bulkId !== null) {
            $queryParams['bulkId'] = $bulkId;
        }
        // query params
        if ($messageId !== null) {
            $queryParams['messageId'] = $messageId;
        }
        // query params
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }




        $headers = $this->headerSelector->selectHeaders(
            ['application/json'],
            []
        );

        // for model (json/xml)
        if (count($formParams) > 0) {
            if ($headers['Content-Type'] === 'multipart/form-data') {
                $boundary = '----'.hash('sha256', uniqid('', true));
                $headers['Content-Type'] .= '; boundary=' . $boundary;
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents, $boundary);
            } 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 API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires HTTP basic authentication
        if (!empty($this->config->getUsername()) || !(empty($this->config->getPassword()))) {
            $headers['Authorization'] = 'Basic ' . base64_encode($this->config->getUsername() . ":" . $this->config->getPassword());
        }
        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if (!empty($this->config->getAccessToken())) {
            $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(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create response for operation 'getEmailDeliveryReports'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\EmailReportsResult|\Infobip\Model\EmailIgnore1ApiException|\Infobip\Model\EmailIgnore1ApiException|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getEmailDeliveryReportsResponse($response, $requestUri)
    {
        $statusCode = $response->getStatusCode();
        $responseBody = $response->getBody();
        $responseHeaders = $response->getHeaders();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                sprintf('[%d] Error connecting to the API (%s)', $statusCode, $requestUri),
                $statusCode,
                $responseHeaders,
                $responseBody
            );
        }

        $responseObject = null;

        if ($statusCode === 200) {
            $type = '\Infobip\Model\EmailReportsResult';
            if ($type === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = (string) $responseBody;
            }
            $responseObject = ObjectSerializer::deserialize($content, $type, $responseHeaders);

            return [
                $responseObject,
                $statusCode,
                $responseHeaders
            ];
        }

        return [
            $responseObject,
            $statusCode,
            $responseHeaders
        ];
    }

    /**
     * Adapt given \Infobip\ApiException for operation 'getEmailDeliveryReports'
     *
     * @param \Infobip\ApiException $apiException
     *
     * @return \Infobip\ApiException
     */
    protected function getEmailDeliveryReportsApiException($apiException)
    {
        $statusCode = $apiException->getCode();

        if ($statusCode === 400) {
            $data = ObjectSerializer::deserialize(
                $apiException->getResponseBody(),
                '\Infobip\Model\EmailIgnore1ApiException',
                $apiException->getResponseHeaders()
            );
            $apiException->setResponseObject($data);
            return $apiException;
        }
        if ($statusCode === 500) {
            $data = ObjectSerializer::deserialize(
                $apiException->getResponseBody(),
                '\Infobip\Model\EmailIgnore1ApiException',
                $apiException->getResponseHeaders()
            );
            $apiException->setResponseObject($data);
            return $apiException;
        }
        return $apiException;
    }

    /**
     * Operation getEmailLogs
     *
     * Get email logs
     *
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  string $from From email address. (optional)
     * @param  string $to The recipient email address. (optional)
     * @param  string $bulkId Bulk ID that uniquely identifies the request. (optional)
     * @param  string $generalStatus Indicates whether the initiated email has been successfully sent, not sent, delivered, not delivered, waiting for delivery or any other possible status. (optional)
     * @param  \DateTime $sentSince Tells when the email was initiated. Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  \DateTime $sentUntil Tells when the email request was processed by Infobip.Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  int $limit Maximum number of logs. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\EmailLogsResponse
     */
    public function getEmailLogs($messageId = null, $from = null, $to = null, $bulkId = null, $generalStatus = null, $sentSince = null, $sentUntil = null, $limit = null)
    {
        list($response) = $this->getEmailLogsWithHttpInfo($messageId, $from, $to, $bulkId, $generalStatus, $sentSince, $sentUntil, $limit);
        return $response;
    }

    /**
     * Operation getEmailLogsWithHttpInfo
     *
     * Get email logs
     *
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  string $from From email address. (optional)
     * @param  string $to The recipient email address. (optional)
     * @param  string $bulkId Bulk ID that uniquely identifies the request. (optional)
     * @param  string $generalStatus Indicates whether the initiated email has been successfully sent, not sent, delivered, not delivered, waiting for delivery or any other possible status. (optional)
     * @param  \DateTime $sentSince Tells when the email was initiated. Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  \DateTime $sentUntil Tells when the email request was processed by Infobip.Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  int $limit Maximum number of logs. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\EmailLogsResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getEmailLogsWithHttpInfo($messageId = null, $from = null, $to = null, $bulkId = null, $generalStatus = null, $sentSince = null, $sentUntil = null, $limit = null)
    {
        $request = $this->getEmailLogsRequest($messageId, $from, $to, $bulkId, $generalStatus, $sentSince, $sentUntil, $limit);

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

    /**
     * Operation getEmailLogsAsync
     *
     * Get email logs
     *
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  string $from From email address. (optional)
     * @param  string $to The recipient email address. (optional)
     * @param  string $bulkId Bulk ID that uniquely identifies the request. (optional)
     * @param  string $generalStatus Indicates whether the initiated email has been successfully sent, not sent, delivered, not delivered, waiting for delivery or any other possible status. (optional)
     * @param  \DateTime $sentSince Tells when the email was initiated. Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  \DateTime $sentUntil Tells when the email request was processed by Infobip.Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  int $limit Maximum number of logs. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getEmailLogsAsync($messageId = null, $from = null, $to = null, $bulkId = null, $generalStatus = null, $sentSince = null, $sentUntil = null, $limit = null)
    {
        return $this->getEmailLogsAsyncWithHttpInfo($messageId, $from, $to, $bulkId, $generalStatus, $sentSince, $sentUntil, $limit)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getEmailLogsAsyncWithHttpInfo
     *
     * Get email logs
     *
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  string $from From email address. (optional)
     * @param  string $to The recipient email address. (optional)
     * @param  string $bulkId Bulk ID that uniquely identifies the request. (optional)
     * @param  string $generalStatus Indicates whether the initiated email has been successfully sent, not sent, delivered, not delivered, waiting for delivery or any other possible status. (optional)
     * @param  \DateTime $sentSince Tells when the email was initiated. Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  \DateTime $sentUntil Tells when the email request was processed by Infobip.Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  int $limit Maximum number of logs. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getEmailLogsAsyncWithHttpInfo($messageId = null, $from = null, $to = null, $bulkId = null, $generalStatus = null, $sentSince = null, $sentUntil = null, $limit = null)
    {
        $request = $this->getEmailLogsRequest($messageId, $from, $to, $bulkId, $generalStatus, $sentSince, $sentUntil, $limit);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getEmailLogsResponse($response, $request->getUri());
                },
                function ($exception) {
                    $statusCode = $exception->getCode();
                    $response = $exception->getResponse();
                    $e = new ApiException(
                        "[{$statusCode}] {$exception->getMessage()}",
                        $statusCode,
                        $response ? $response->getHeaders() : null,
                        $response ? (string) $response->getBody() : null
                    );
                    throw $this->getEmailLogsApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getEmailLogs'
     *
     * @param  string $messageId The ID that uniquely identifies the sent email. (optional)
     * @param  string $from From email address. (optional)
     * @param  string $to The recipient email address. (optional)
     * @param  string $bulkId Bulk ID that uniquely identifies the request. (optional)
     * @param  string $generalStatus Indicates whether the initiated email has been successfully sent, not sent, delivered, not delivered, waiting for delivery or any other possible status. (optional)
     * @param  \DateTime $sentSince Tells when the email was initiated. Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  \DateTime $sentUntil Tells when the email request was processed by Infobip.Has the following format: &#x60;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ&#x60;. (optional)
     * @param  int $limit Maximum number of logs. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getEmailLogsRequest($messageId = null, $from = null, $to = null, $bulkId = null, $generalStatus = null, $sentSince = null, $sentUntil = null, $limit = null)
    {
        $resourcePath = '/email/1/logs';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';

        // query params
        if ($messageId !== null) {
            $queryParams['messageId'] = $messageId;
        }
        // query params
        if ($from !== null) {
            $queryParams['from'] = $from;
        }
        // query params
        if ($to !== null) {
            $queryParams['to'] = $to;
        }
        // query params
        if ($bulkId !== null) {
            $queryParams['bulkId'] = $bulkId;
        }
        // query params
        if ($generalStatus !== null) {
            $queryParams['generalStatus'] = $generalStatus;
        }
        // query params
        if ($sentSince !== null) {
            $queryParams['sentSince'] = $sentSince;
        }
        // query params
        if ($sentUntil !== null) {
            $queryParams['sentUntil'] = $sentUntil;
        }
        // query params
        if ($limit !== null) {
            $queryParams['limit'] = $limit;
        }




        $headers = $this->headerSelector->selectHeaders(
            ['application/json'],
            []
        );

        // for model (json/xml)
        if (count($formParams) > 0) {
            if ($headers['Content-Type'] === 'multipart/form-data') {
                $boundary = '----'.hash('sha256', uniqid('', true));
                $headers['Content-Type'] .= '; boundary=' . $boundary;
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents, $boundary);
            } 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 API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires HTTP basic authentication
        if (!empty($this->config->getUsername()) || !(empty($this->config->getPassword()))) {
            $headers['Authorization'] = 'Basic ' . base64_encode($this->config->getUsername() . ":" . $this->config->getPassword());
        }
        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if (!empty($this->config->getAccessToken())) {
            $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(
            'GET',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create response for operation 'getEmailLogs'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\EmailLogsResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getEmailLogsResponse($response, $requestUri)
    {
        $statusCode = $response->getStatusCode();
        $responseBody = $response->getBody();
        $responseHeaders = $response->getHeaders();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                sprintf('[%d] Error connecting to the API (%s)', $statusCode, $requestUri),
                $statusCode,
                $responseHeaders,
                $responseBody
            );
        }

        $responseObject = null;

        if ($statusCode === 200) {
            $type = '\Infobip\Model\EmailLogsResponse';
            if ($type === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = (string) $responseBody;
            }
            $responseObject = ObjectSerializer::deserialize($content, $type, $responseHeaders);

            return [
                $responseObject,
                $statusCode,
                $responseHeaders
            ];
        }

        return [
            $responseObject,
            $statusCode,
            $responseHeaders
        ];
    }

    /**
     * Adapt given \Infobip\ApiException for operation 'getEmailLogs'
     *
     * @param \Infobip\ApiException $apiException
     *
     * @return \Infobip\ApiException
     */
    protected function getEmailLogsApiException($apiException)
    {
        $statusCode = $apiException->getCode();

        return $apiException;
    }

    /**
     * Operation sendEmail
     *
     * Send fully featured email
     *
     * Note: the input parameter is an associative array with the keys listed as the parameter name below
     *
     * @param  string $from Email address with optional sender name. (required)
     * @param  string $to Email address of the recipient. (required)
     * @param  string $cc CC recipient email address. (optional)
     * @param  string $bcc BCC recipient email address. (optional)
     * @param  string $subject Message subject.  NOTE: This field is required if templateId is blank (optional)
     * @param  string $text Body of the message. (optional)
     * @param  string $html HTML body of the message. If HTML and text fields are present, the text field will be ignored and HTML will be delivered as a message body. (optional)
     * @param  int $templateId Template identifier based on which the email message is generated. The template is created over Infobip web interface. If templateId is present then HTML and text values are ignored. NOTE: This field supports the value of broadcast templateId only. Content templateId is not supported. (optional)
     * @param  \SplFileObject $attachment File attachment. (optional)
     * @param  \SplFileObject $inlineImage Using an inline image, it is possible to insert the image file inside the HTML code of the email by using cid:FILENAME instead of providing an external link to the image. (optional)
     * @param  string $bulkId The ID uniquely identifies the sent Email request. This filter will enable you to query delivery reports for all the messages using just one request. You will receive a bulkId in the response after sending an email request. If you don&#39;t set your own bulkId, unique ID will be generated by our system and returned in the API response. (Optional Field) (optional)
     * @param  string $messageId The ID that uniquely identifies the message sent to a recipient. (Optional Field) (optional)
     * @param  string $replyTo Email address to which recipients of the email can reply. (optional)
     * @param  string $defaultPlaceholders Default placeholder values used for all recipients. The values are used to generate the email message. (optional)
     * @param  bool $preserveRecipients This parameter enables preserving recipients for an email when the value is true, the default value is false for this parameter. (optional)
     * @param  string $trackingUrl The URL on your callback server on which the open and click notifications will be sent. If you are passing this parameter then track&#x3D;true will be assigned, you don&#39;t need to pass track&#x3D;true separately. See the section \\\&quot;Tracking Notifications\\\&quot; below for details. (optional)
     * @param  bool $trackClicks This parameter enables or disables track click feature. (optional)
     * @param  bool $trackOpens This parameter enables or disables track open feature. (optional)
     * @param  bool $track Enable or disable open and click tracking. The default value is true. Passing true will only enable tracking and the statistics would be visible in the web interface alone. This can be explicitly overridden by trackOpens and trackClicks. (optional)
     * @param  string $callbackData Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters. (optional)
     * @param  bool $intermediateReport The real-time Intermediate delivery report that will be sent on your callback server. (optional)
     * @param  string $notifyUrl The URL on your callback server on which the Delivery report will be sent. (optional)
     * @param  string $notifyContentType Preferred Delivery report content type. Can be application/json or application/xml. (optional)
     * @param  \DateTime $sendAt To schedule message at a given time in future. Time provided should be in UTC in the following format: yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ. (optional)
     * @param  string $landingPagePlaceholders Personalize opt out landing page by inserting placeholders. Insert placeholder or tag while designing landing page. (optional)
     * @param  string $landingPageId Opt out landing page which will be used and displayed once end user clicks the unsubscribe link. If not present default opt out landing page will be displayed. Create a landing page on IB’s portal and use the last 6 digits from URL to use that opt out page. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\EmailSendResponse|\Infobip\Model\EmailApiException|\Infobip\Model\EmailApiException
     */
    public function sendEmail($associative_array)
    {
        list($response) = $this->sendEmailWithHttpInfo($associative_array);
        return $response;
    }

    /**
     * Operation sendEmailWithHttpInfo
     *
     * Send fully featured email
     *
     * Note: the input parameter is an associative array with the keys listed as the parameter name below
     *
     * @param  string $from Email address with optional sender name. (required)
     * @param  string $to Email address of the recipient. (required)
     * @param  string $cc CC recipient email address. (optional)
     * @param  string $bcc BCC recipient email address. (optional)
     * @param  string $subject Message subject.  NOTE: This field is required if templateId is blank (optional)
     * @param  string $text Body of the message. (optional)
     * @param  string $html HTML body of the message. If HTML and text fields are present, the text field will be ignored and HTML will be delivered as a message body. (optional)
     * @param  int $templateId Template identifier based on which the email message is generated. The template is created over Infobip web interface. If templateId is present then HTML and text values are ignored. NOTE: This field supports the value of broadcast templateId only. Content templateId is not supported. (optional)
     * @param  \SplFileObject $attachment File attachment. (optional)
     * @param  \SplFileObject $inlineImage Using an inline image, it is possible to insert the image file inside the HTML code of the email by using cid:FILENAME instead of providing an external link to the image. (optional)
     * @param  string $bulkId The ID uniquely identifies the sent Email request. This filter will enable you to query delivery reports for all the messages using just one request. You will receive a bulkId in the response after sending an email request. If you don&#39;t set your own bulkId, unique ID will be generated by our system and returned in the API response. (Optional Field) (optional)
     * @param  string $messageId The ID that uniquely identifies the message sent to a recipient. (Optional Field) (optional)
     * @param  string $replyTo Email address to which recipients of the email can reply. (optional)
     * @param  string $defaultPlaceholders Default placeholder values used for all recipients. The values are used to generate the email message. (optional)
     * @param  bool $preserveRecipients This parameter enables preserving recipients for an email when the value is true, the default value is false for this parameter. (optional)
     * @param  string $trackingUrl The URL on your callback server on which the open and click notifications will be sent. If you are passing this parameter then track&#x3D;true will be assigned, you don&#39;t need to pass track&#x3D;true separately. See the section \\\&quot;Tracking Notifications\\\&quot; below for details. (optional)
     * @param  bool $trackClicks This parameter enables or disables track click feature. (optional)
     * @param  bool $trackOpens This parameter enables or disables track open feature. (optional)
     * @param  bool $track Enable or disable open and click tracking. The default value is true. Passing true will only enable tracking and the statistics would be visible in the web interface alone. This can be explicitly overridden by trackOpens and trackClicks. (optional)
     * @param  string $callbackData Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters. (optional)
     * @param  bool $intermediateReport The real-time Intermediate delivery report that will be sent on your callback server. (optional)
     * @param  string $notifyUrl The URL on your callback server on which the Delivery report will be sent. (optional)
     * @param  string $notifyContentType Preferred Delivery report content type. Can be application/json or application/xml. (optional)
     * @param  \DateTime $sendAt To schedule message at a given time in future. Time provided should be in UTC in the following format: yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ. (optional)
     * @param  string $landingPagePlaceholders Personalize opt out landing page by inserting placeholders. Insert placeholder or tag while designing landing page. (optional)
     * @param  string $landingPageId Opt out landing page which will be used and displayed once end user clicks the unsubscribe link. If not present default opt out landing page will be displayed. Create a landing page on IB’s portal and use the last 6 digits from URL to use that opt out page. (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\EmailSendResponse|\Infobip\Model\EmailApiException|\Infobip\Model\EmailApiException, HTTP status code, HTTP response headers (array of strings)
     */
    public function sendEmailWithHttpInfo($associative_array)
    {
        $request = $this->sendEmailRequest($associative_array);

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

    /**
     * Operation sendEmailAsync
     *
     * Send fully featured email
     *
     * Note: the input parameter is an associative array with the keys listed as the parameter name below
     *
     * @param  string $from Email address with optional sender name. (required)
     * @param  string $to Email address of the recipient. (required)
     * @param  string $cc CC recipient email address. (optional)
     * @param  string $bcc BCC recipient email address. (optional)
     * @param  string $subject Message subject.  NOTE: This field is required if templateId is blank (optional)
     * @param  string $text Body of the message. (optional)
     * @param  string $html HTML body of the message. If HTML and text fields are present, the text field will be ignored and HTML will be delivered as a message body. (optional)
     * @param  int $templateId Template identifier based on which the email message is generated. The template is created over Infobip web interface. If templateId is present then HTML and text values are ignored. NOTE: This field supports the value of broadcast templateId only. Content templateId is not supported. (optional)
     * @param  \SplFileObject $attachment File attachment. (optional)
     * @param  \SplFileObject $inlineImage Using an inline image, it is possible to insert the image file inside the HTML code of the email by using cid:FILENAME instead of providing an external link to the image. (optional)
     * @param  string $bulkId The ID uniquely identifies the sent Email request. This filter will enable you to query delivery reports for all the messages using just one request. You will receive a bulkId in the response after sending an email request. If you don&#39;t set your own bulkId, unique ID will be generated by our system and returned in the API response. (Optional Field) (optional)
     * @param  string $messageId The ID that uniquely identifies the message sent to a recipient. (Optional Field) (optional)
     * @param  string $replyTo Email address to which recipients of the email can reply. (optional)
     * @param  string $defaultPlaceholders Default placeholder values used for all recipients. The values are used to generate the email message. (optional)
     * @param  bool $preserveRecipients This parameter enables preserving recipients for an email when the value is true, the default value is false for this parameter. (optional)
     * @param  string $trackingUrl The URL on your callback server on which the open and click notifications will be sent. If you are passing this parameter then track&#x3D;true will be assigned, you don&#39;t need to pass track&#x3D;true separately. See the section \\\&quot;Tracking Notifications\\\&quot; below for details. (optional)
     * @param  bool $trackClicks This parameter enables or disables track click feature. (optional)
     * @param  bool $trackOpens This parameter enables or disables track open feature. (optional)
     * @param  bool $track Enable or disable open and click tracking. The default value is true. Passing true will only enable tracking and the statistics would be visible in the web interface alone. This can be explicitly overridden by trackOpens and trackClicks. (optional)
     * @param  string $callbackData Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters. (optional)
     * @param  bool $intermediateReport The real-time Intermediate delivery report that will be sent on your callback server. (optional)
     * @param  string $notifyUrl The URL on your callback server on which the Delivery report will be sent. (optional)
     * @param  string $notifyContentType Preferred Delivery report content type. Can be application/json or application/xml. (optional)
     * @param  \DateTime $sendAt To schedule message at a given time in future. Time provided should be in UTC in the following format: yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ. (optional)
     * @param  string $landingPagePlaceholders Personalize opt out landing page by inserting placeholders. Insert placeholder or tag while designing landing page. (optional)
     * @param  string $landingPageId Opt out landing page which will be used and displayed once end user clicks the unsubscribe link. If not present default opt out landing page will be displayed. Create a landing page on IB’s portal and use the last 6 digits from URL to use that opt out page. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendEmailAsync($associative_array)
    {
        return $this->sendEmailAsyncWithHttpInfo($associative_array)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation sendEmailAsyncWithHttpInfo
     *
     * Send fully featured email
     *
     * Note: the input parameter is an associative array with the keys listed as the parameter name below
     *
     * @param  string $from Email address with optional sender name. (required)
     * @param  string $to Email address of the recipient. (required)
     * @param  string $cc CC recipient email address. (optional)
     * @param  string $bcc BCC recipient email address. (optional)
     * @param  string $subject Message subject.  NOTE: This field is required if templateId is blank (optional)
     * @param  string $text Body of the message. (optional)
     * @param  string $html HTML body of the message. If HTML and text fields are present, the text field will be ignored and HTML will be delivered as a message body. (optional)
     * @param  int $templateId Template identifier based on which the email message is generated. The template is created over Infobip web interface. If templateId is present then HTML and text values are ignored. NOTE: This field supports the value of broadcast templateId only. Content templateId is not supported. (optional)
     * @param  \SplFileObject $attachment File attachment. (optional)
     * @param  \SplFileObject $inlineImage Using an inline image, it is possible to insert the image file inside the HTML code of the email by using cid:FILENAME instead of providing an external link to the image. (optional)
     * @param  string $bulkId The ID uniquely identifies the sent Email request. This filter will enable you to query delivery reports for all the messages using just one request. You will receive a bulkId in the response after sending an email request. If you don&#39;t set your own bulkId, unique ID will be generated by our system and returned in the API response. (Optional Field) (optional)
     * @param  string $messageId The ID that uniquely identifies the message sent to a recipient. (Optional Field) (optional)
     * @param  string $replyTo Email address to which recipients of the email can reply. (optional)
     * @param  string $defaultPlaceholders Default placeholder values used for all recipients. The values are used to generate the email message. (optional)
     * @param  bool $preserveRecipients This parameter enables preserving recipients for an email when the value is true, the default value is false for this parameter. (optional)
     * @param  string $trackingUrl The URL on your callback server on which the open and click notifications will be sent. If you are passing this parameter then track&#x3D;true will be assigned, you don&#39;t need to pass track&#x3D;true separately. See the section \\\&quot;Tracking Notifications\\\&quot; below for details. (optional)
     * @param  bool $trackClicks This parameter enables or disables track click feature. (optional)
     * @param  bool $trackOpens This parameter enables or disables track open feature. (optional)
     * @param  bool $track Enable or disable open and click tracking. The default value is true. Passing true will only enable tracking and the statistics would be visible in the web interface alone. This can be explicitly overridden by trackOpens and trackClicks. (optional)
     * @param  string $callbackData Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters. (optional)
     * @param  bool $intermediateReport The real-time Intermediate delivery report that will be sent on your callback server. (optional)
     * @param  string $notifyUrl The URL on your callback server on which the Delivery report will be sent. (optional)
     * @param  string $notifyContentType Preferred Delivery report content type. Can be application/json or application/xml. (optional)
     * @param  \DateTime $sendAt To schedule message at a given time in future. Time provided should be in UTC in the following format: yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ. (optional)
     * @param  string $landingPagePlaceholders Personalize opt out landing page by inserting placeholders. Insert placeholder or tag while designing landing page. (optional)
     * @param  string $landingPageId Opt out landing page which will be used and displayed once end user clicks the unsubscribe link. If not present default opt out landing page will be displayed. Create a landing page on IB’s portal and use the last 6 digits from URL to use that opt out page. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendEmailAsyncWithHttpInfo($associative_array)
    {
        $request = $this->sendEmailRequest($associative_array);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->sendEmailResponse($response, $request->getUri());
                },
                function ($exception) {
                    $statusCode = $exception->getCode();
                    $response = $exception->getResponse();
                    $e = new ApiException(
                        "[{$statusCode}] {$exception->getMessage()}",
                        $statusCode,
                        $response ? $response->getHeaders() : null,
                        $response ? (string) $response->getBody() : null
                    );
                    throw $this->sendEmailApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'sendEmail'
     *
     * Note: the input parameter is an associative array with the keys listed as the parameter name below
     *
     * @param  string $from Email address with optional sender name. (required)
     * @param  string $to Email address of the recipient. (required)
     * @param  string $cc CC recipient email address. (optional)
     * @param  string $bcc BCC recipient email address. (optional)
     * @param  string $subject Message subject.  NOTE: This field is required if templateId is blank (optional)
     * @param  string $text Body of the message. (optional)
     * @param  string $html HTML body of the message. If HTML and text fields are present, the text field will be ignored and HTML will be delivered as a message body. (optional)
     * @param  int $templateId Template identifier based on which the email message is generated. The template is created over Infobip web interface. If templateId is present then HTML and text values are ignored. NOTE: This field supports the value of broadcast templateId only. Content templateId is not supported. (optional)
     * @param  \SplFileObject $attachment File attachment. (optional)
     * @param  \SplFileObject $inlineImage Using an inline image, it is possible to insert the image file inside the HTML code of the email by using cid:FILENAME instead of providing an external link to the image. (optional)
     * @param  string $bulkId The ID uniquely identifies the sent Email request. This filter will enable you to query delivery reports for all the messages using just one request. You will receive a bulkId in the response after sending an email request. If you don&#39;t set your own bulkId, unique ID will be generated by our system and returned in the API response. (Optional Field) (optional)
     * @param  string $messageId The ID that uniquely identifies the message sent to a recipient. (Optional Field) (optional)
     * @param  string $replyTo Email address to which recipients of the email can reply. (optional)
     * @param  string $defaultPlaceholders Default placeholder values used for all recipients. The values are used to generate the email message. (optional)
     * @param  bool $preserveRecipients This parameter enables preserving recipients for an email when the value is true, the default value is false for this parameter. (optional)
     * @param  string $trackingUrl The URL on your callback server on which the open and click notifications will be sent. If you are passing this parameter then track&#x3D;true will be assigned, you don&#39;t need to pass track&#x3D;true separately. See the section \\\&quot;Tracking Notifications\\\&quot; below for details. (optional)
     * @param  bool $trackClicks This parameter enables or disables track click feature. (optional)
     * @param  bool $trackOpens This parameter enables or disables track open feature. (optional)
     * @param  bool $track Enable or disable open and click tracking. The default value is true. Passing true will only enable tracking and the statistics would be visible in the web interface alone. This can be explicitly overridden by trackOpens and trackClicks. (optional)
     * @param  string $callbackData Additional client data that will be sent on the notifyUrl. The maximum value is 4000 characters. (optional)
     * @param  bool $intermediateReport The real-time Intermediate delivery report that will be sent on your callback server. (optional)
     * @param  string $notifyUrl The URL on your callback server on which the Delivery report will be sent. (optional)
     * @param  string $notifyContentType Preferred Delivery report content type. Can be application/json or application/xml. (optional)
     * @param  \DateTime $sendAt To schedule message at a given time in future. Time provided should be in UTC in the following format: yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSSZ. (optional)
     * @param  string $landingPagePlaceholders Personalize opt out landing page by inserting placeholders. Insert placeholder or tag while designing landing page. (optional)
     * @param  string $landingPageId Opt out landing page which will be used and displayed once end user clicks the unsubscribe link. If not present default opt out landing page will be displayed. Create a landing page on IB’s portal and use the last 6 digits from URL to use that opt out page. (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function sendEmailRequest($associative_array)
    {
        // unbox the parameters from the associative array
        $from = array_key_exists('from', $associative_array) ? $associative_array['from'] : null;
        $to = array_key_exists('to', $associative_array) ? $associative_array['to'] : null;
        $cc = array_key_exists('cc', $associative_array) ? $associative_array['cc'] : null;
        $bcc = array_key_exists('bcc', $associative_array) ? $associative_array['bcc'] : null;
        $subject = array_key_exists('subject', $associative_array) ? $associative_array['subject'] : null;
        $text = array_key_exists('text', $associative_array) ? $associative_array['text'] : null;
        $html = array_key_exists('html', $associative_array) ? $associative_array['html'] : null;
        $templateId = array_key_exists('templateId', $associative_array) ? $associative_array['templateId'] : null;
        $attachment = array_key_exists('attachment', $associative_array) ? $associative_array['attachment'] : null;
        $inlineImage = array_key_exists('inlineImage', $associative_array) ? $associative_array['inlineImage'] : null;
        $bulkId = array_key_exists('bulkId', $associative_array) ? $associative_array['bulkId'] : null;
        $messageId = array_key_exists('messageId', $associative_array) ? $associative_array['messageId'] : null;
        $replyTo = array_key_exists('replyTo', $associative_array) ? $associative_array['replyTo'] : null;
        $defaultPlaceholders = array_key_exists('defaultPlaceholders', $associative_array) ? $associative_array['defaultPlaceholders'] : null;
        $preserveRecipients = array_key_exists('preserveRecipients', $associative_array) ? $associative_array['preserveRecipients'] : null;
        $trackingUrl = array_key_exists('trackingUrl', $associative_array) ? $associative_array['trackingUrl'] : null;
        $trackClicks = array_key_exists('trackClicks', $associative_array) ? $associative_array['trackClicks'] : null;
        $trackOpens = array_key_exists('trackOpens', $associative_array) ? $associative_array['trackOpens'] : null;
        $track = array_key_exists('track', $associative_array) ? $associative_array['track'] : null;
        $callbackData = array_key_exists('callbackData', $associative_array) ? $associative_array['callbackData'] : null;
        $intermediateReport = array_key_exists('intermediateReport', $associative_array) ? $associative_array['intermediateReport'] : null;
        $notifyUrl = array_key_exists('notifyUrl', $associative_array) ? $associative_array['notifyUrl'] : null;
        $notifyContentType = array_key_exists('notifyContentType', $associative_array) ? $associative_array['notifyContentType'] : null;
        $sendAt = array_key_exists('sendAt', $associative_array) ? $associative_array['sendAt'] : null;
        $landingPagePlaceholders = array_key_exists('landingPagePlaceholders', $associative_array) ? $associative_array['landingPagePlaceholders'] : null;
        $landingPageId = array_key_exists('landingPageId', $associative_array) ? $associative_array['landingPageId'] : null;

        // verify the required parameter 'from' is set
        if ($from === null || (is_array($from) && count($from) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $from when calling sendEmail'
            );
        }
        // verify the required parameter 'to' is set
        if ($to === null || (is_array($to) && count($to) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $to when calling sendEmail'
            );
        }

        $resourcePath = '/email/2/send';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';




        // form params
        if ($from !== null) {
            $formParams['from'] = ObjectSerializer::toFormValue($from);
        }
        // form params
        if ($to !== null) {
            $formParams['to'] = ObjectSerializer::toFormValue($to);
        }
        // form params
        if ($cc !== null) {
            $formParams['cc'] = ObjectSerializer::toFormValue($cc);
        }
        // form params
        if ($bcc !== null) {
            $formParams['bcc'] = ObjectSerializer::toFormValue($bcc);
        }
        // form params
        if ($subject !== null) {
            $formParams['subject'] = ObjectSerializer::toFormValue($subject);
        }
        // form params
        if ($text !== null) {
            $formParams['text'] = ObjectSerializer::toFormValue($text);
        }
        // form params
        if ($html !== null) {
            $formParams['html'] = ObjectSerializer::toFormValue($html);
        }
        // form params
        if ($templateId !== null) {
            $formParams['templateId'] = ObjectSerializer::toFormValue($templateId);
        }
        // form params
        if ($attachment !== null) {
            $formParams['attachment'] = [];
            $paramFiles = is_array($attachment) ? $attachment : [$attachment];
            foreach ($paramFiles as $paramFile) {
                $formParams['attachment'][] = Utils::tryFopen(
                    ObjectSerializer::toFormValue($paramFile),
                    'rb'
                );
            }
        }
        // form params
        if ($inlineImage !== null) {
            $formParams['inlineImage'] = [];
            $paramFiles = is_array($inlineImage) ? $inlineImage : [$inlineImage];
            foreach ($paramFiles as $paramFile) {
                $formParams['inlineImage'][] = Utils::tryFopen(
                    ObjectSerializer::toFormValue($paramFile),
                    'rb'
                );
            }
        }
        // form params
        if ($bulkId !== null) {
            $formParams['bulkId'] = ObjectSerializer::toFormValue($bulkId);
        }
        // form params
        if ($messageId !== null) {
            $formParams['messageId'] = ObjectSerializer::toFormValue($messageId);
        }
        // form params
        if ($replyTo !== null) {
            $formParams['replyTo'] = ObjectSerializer::toFormValue($replyTo);
        }
        // form params
        if ($defaultPlaceholders !== null) {
            $formParams['defaultPlaceholders'] = ObjectSerializer::toFormValue($defaultPlaceholders);
        }
        // form params
        if ($preserveRecipients !== null) {
            $formParams['preserveRecipients'] = ObjectSerializer::toFormValue($preserveRecipients);
        }
        // form params
        if ($trackingUrl !== null) {
            $formParams['trackingUrl'] = ObjectSerializer::toFormValue($trackingUrl);
        }
        // form params
        if ($trackClicks !== null) {
            $formParams['trackClicks'] = ObjectSerializer::toFormValue($trackClicks);
        }
        // form params
        if ($trackOpens !== null) {
            $formParams['trackOpens'] = ObjectSerializer::toFormValue($trackOpens);
        }
        // form params
        if ($track !== null) {
            $formParams['track'] = ObjectSerializer::toFormValue($track);
        }
        // form params
        if ($callbackData !== null) {
            $formParams['callbackData'] = ObjectSerializer::toFormValue($callbackData);
        }
        // form params
        if ($intermediateReport !== null) {
            $formParams['intermediateReport'] = ObjectSerializer::toFormValue($intermediateReport);
        }
        // form params
        if ($notifyUrl !== null) {
            $formParams['notifyUrl'] = ObjectSerializer::toFormValue($notifyUrl);
        }
        // form params
        if ($notifyContentType !== null) {
            $formParams['notifyContentType'] = ObjectSerializer::toFormValue($notifyContentType);
        }
        // form params
        if ($sendAt !== null) {
            $formParams['sendAt'] = ObjectSerializer::toFormValue($sendAt);
        }
        // form params
        if ($landingPagePlaceholders !== null) {
            $formParams['landingPagePlaceholders'] = ObjectSerializer::toFormValue($landingPagePlaceholders);
        }
        // form params
        if ($landingPageId !== null) {
            $formParams['landingPageId'] = ObjectSerializer::toFormValue($landingPageId);
        }

        $headers = $this->headerSelector->selectHeaders(
            ['application/json', 'application/xml'],
            ['multipart/form-data']
        );

        // for model (json/xml)
        if (count($formParams) > 0) {
            if ($headers['Content-Type'] === 'multipart/form-data') {
                $boundary = '----'.hash('sha256', uniqid('', true));
                $headers['Content-Type'] .= '; boundary=' . $boundary;
                $multipartContents = [];
                foreach ($formParams as $formParamName => $formParamValue) {
                    $formParamValueItems = is_array($formParamValue) ? $formParamValue : [$formParamValue];
                    foreach ($formParamValueItems as $formParamValueItem) {
                        $multipartContents[] = [
                            'name' => $formParamName,
                            'contents' => $formParamValueItem
                        ];
                    }
                }
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents, $boundary);
            } 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 API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires HTTP basic authentication
        if (!empty($this->config->getUsername()) || !(empty($this->config->getPassword()))) {
            $headers['Authorization'] = 'Basic ' . base64_encode($this->config->getUsername() . ":" . $this->config->getPassword());
        }
        // this endpoint requires API key authentication
        $apiKey = $this->config->getApiKeyWithPrefix('Authorization');
        if ($apiKey !== null) {
            $headers['Authorization'] = $apiKey;
        }
        // this endpoint requires OAuth (access token)
        if (!empty($this->config->getAccessToken())) {
            $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 response for operation 'sendEmail'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\EmailSendResponse|\Infobip\Model\EmailApiException|\Infobip\Model\EmailApiException|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function sendEmailResponse($response, $requestUri)
    {
        $statusCode = $response->getStatusCode();
        $responseBody = $response->getBody();
        $responseHeaders = $response->getHeaders();

        if ($statusCode < 200 || $statusCode > 299) {
            throw new ApiException(
                sprintf('[%d] Error connecting to the API (%s)', $statusCode, $requestUri),
                $statusCode,
                $responseHeaders,
                $responseBody
            );
        }

        $responseObject = null;

        if ($statusCode === 200) {
            $type = '\Infobip\Model\EmailSendResponse';
            if ($type === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = (string) $responseBody;
            }
            $responseObject = ObjectSerializer::deserialize($content, $type, $responseHeaders);

            return [
                $responseObject,
                $statusCode,
                $responseHeaders
            ];
        }

        return [
            $responseObject,
            $statusCode,
            $responseHeaders
        ];
    }

    /**
     * Adapt given \Infobip\ApiException for operation 'sendEmail'
     *
     * @param \Infobip\ApiException $apiException
     *
     * @return \Infobip\ApiException
     */
    protected function sendEmailApiException($apiException)
    {
        $statusCode = $apiException->getCode();

        if ($statusCode >= 400 && $statusCode <= 499) {
            $data = ObjectSerializer::deserialize(
                $apiException->getResponseBody(),
                '\Infobip\Model\EmailApiException',
                $apiException->getResponseHeaders()
            );
            $apiException->setResponseObject($data);
            return $apiException;
        }
        if ($statusCode >= 500 && $statusCode <= 599) {
            $data = ObjectSerializer::deserialize(
                $apiException->getResponseBody(),
                '\Infobip\Model\EmailApiException',
                $apiException->getResponseHeaders()
            );
            $apiException->setResponseObject($data);
            return $apiException;
        }
        return $apiException;
    }

    /**
     * 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;
    }
}
