<?php
/**
 * TfaApi
 * 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;

/**
 * TfaApi Class Doc Comment
 *
 * @category Class
 * @package  Infobip
 * @author   Infobip Support
 * @link     https://www.infobip.com
 */
class TfaApi
{
    /**
     * @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 createTfaApplication
     *
     * Create 2FA application
     *
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest tfaApplicationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse
     */
    public function createTfaApplication($tfaApplicationRequest = null)
    {
        list($response) = $this->createTfaApplicationWithHttpInfo($tfaApplicationRequest);
        return $response;
    }

    /**
     * Operation createTfaApplicationWithHttpInfo
     *
     * Create 2FA application
     *
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function createTfaApplicationWithHttpInfo($tfaApplicationRequest = null)
    {
        $request = $this->createTfaApplicationRequest($tfaApplicationRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->createTfaApplicationResponse($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->createTfaApplicationApiException($e);
        }
    }

    /**
     * Operation createTfaApplicationAsync
     *
     * Create 2FA application
     *
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createTfaApplicationAsync($tfaApplicationRequest = null)
    {
        return $this->createTfaApplicationAsyncWithHttpInfo($tfaApplicationRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation createTfaApplicationAsyncWithHttpInfo
     *
     * Create 2FA application
     *
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createTfaApplicationAsyncWithHttpInfo($tfaApplicationRequest = null)
    {
        $request = $this->createTfaApplicationRequest($tfaApplicationRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->createTfaApplicationResponse($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->createTfaApplicationApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'createTfaApplication'
     *
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function createTfaApplicationRequest($tfaApplicationRequest = null)
    {
        $resourcePath = '/2fa/2/applications';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';





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

        // for model (json/xml)
        if (isset($tfaApplicationRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaApplicationRequest));
            } else {
                $httpBody = $tfaApplicationRequest;
            }
        } elseif (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 'createTfaApplication'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function createTfaApplicationResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaApplicationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation createTfaMessageTemplate
     *
     * Create 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  \Infobip\Model\TfaCreateMessageRequest $tfaCreateMessageRequest tfaCreateMessageRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage
     */
    public function createTfaMessageTemplate($appId, $tfaCreateMessageRequest = null)
    {
        list($response) = $this->createTfaMessageTemplateWithHttpInfo($appId, $tfaCreateMessageRequest);
        return $response;
    }

    /**
     * Operation createTfaMessageTemplateWithHttpInfo
     *
     * Create 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  \Infobip\Model\TfaCreateMessageRequest $tfaCreateMessageRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage, HTTP status code, HTTP response headers (array of strings)
     */
    public function createTfaMessageTemplateWithHttpInfo($appId, $tfaCreateMessageRequest = null)
    {
        $request = $this->createTfaMessageTemplateRequest($appId, $tfaCreateMessageRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->createTfaMessageTemplateResponse($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->createTfaMessageTemplateApiException($e);
        }
    }

    /**
     * Operation createTfaMessageTemplateAsync
     *
     * Create 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  \Infobip\Model\TfaCreateMessageRequest $tfaCreateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createTfaMessageTemplateAsync($appId, $tfaCreateMessageRequest = null)
    {
        return $this->createTfaMessageTemplateAsyncWithHttpInfo($appId, $tfaCreateMessageRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation createTfaMessageTemplateAsyncWithHttpInfo
     *
     * Create 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  \Infobip\Model\TfaCreateMessageRequest $tfaCreateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createTfaMessageTemplateAsyncWithHttpInfo($appId, $tfaCreateMessageRequest = null)
    {
        $request = $this->createTfaMessageTemplateRequest($appId, $tfaCreateMessageRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->createTfaMessageTemplateResponse($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->createTfaMessageTemplateApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'createTfaMessageTemplate'
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  \Infobip\Model\TfaCreateMessageRequest $tfaCreateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function createTfaMessageTemplateRequest($appId, $tfaCreateMessageRequest = null)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling createTfaMessageTemplate'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}/messages';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaCreateMessageRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaCreateMessageRequest));
            } else {
                $httpBody = $tfaCreateMessageRequest;
            }
        } elseif (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 'createTfaMessageTemplate'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function createTfaMessageTemplateResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaMessage',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation getTfaApplication
     *
     * Get 2FA application
     *
     * @param  string $appId ID of application for which configuration view was requested. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse
     */
    public function getTfaApplication($appId)
    {
        list($response) = $this->getTfaApplicationWithHttpInfo($appId);
        return $response;
    }

    /**
     * Operation getTfaApplicationWithHttpInfo
     *
     * Get 2FA application
     *
     * @param  string $appId ID of application for which configuration view was requested. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTfaApplicationWithHttpInfo($appId)
    {
        $request = $this->getTfaApplicationRequest($appId);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->getTfaApplicationResponse($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->getTfaApplicationApiException($e);
        }
    }

    /**
     * Operation getTfaApplicationAsync
     *
     * Get 2FA application
     *
     * @param  string $appId ID of application for which configuration view was requested. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaApplicationAsync($appId)
    {
        return $this->getTfaApplicationAsyncWithHttpInfo($appId)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getTfaApplicationAsyncWithHttpInfo
     *
     * Get 2FA application
     *
     * @param  string $appId ID of application for which configuration view was requested. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaApplicationAsyncWithHttpInfo($appId)
    {
        $request = $this->getTfaApplicationRequest($appId);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getTfaApplicationResponse($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->getTfaApplicationApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getTfaApplication'
     *
     * @param  string $appId ID of application for which configuration view was requested. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getTfaApplicationRequest($appId)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling getTfaApplication'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // 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 'getTfaApplication'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getTfaApplicationResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaApplicationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation getTfaApplications
     *
     * Get 2FA applications
     *
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse[]
     */
    public function getTfaApplications()
    {
        list($response) = $this->getTfaApplicationsWithHttpInfo();
        return $response;
    }

    /**
     * Operation getTfaApplicationsWithHttpInfo
     *
     * Get 2FA applications
     *
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse[], HTTP status code, HTTP response headers (array of strings)
     */
    public function getTfaApplicationsWithHttpInfo()
    {
        $request = $this->getTfaApplicationsRequest();

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->getTfaApplicationsResponse($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->getTfaApplicationsApiException($e);
        }
    }

    /**
     * Operation getTfaApplicationsAsync
     *
     * Get 2FA applications
     *
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaApplicationsAsync()
    {
        return $this->getTfaApplicationsAsyncWithHttpInfo()
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getTfaApplicationsAsyncWithHttpInfo
     *
     * Get 2FA applications
     *
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaApplicationsAsyncWithHttpInfo()
    {
        $request = $this->getTfaApplicationsRequest();

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getTfaApplicationsResponse($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->getTfaApplicationsApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getTfaApplications'
     *
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getTfaApplicationsRequest()
    {
        $resourcePath = '/2fa/2/applications';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';





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

        // 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 'getTfaApplications'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse[]|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getTfaApplicationsResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaApplicationResponse[]',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation getTfaMessageTemplate
     *
     * Get 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage
     */
    public function getTfaMessageTemplate($appId, $msgId)
    {
        list($response) = $this->getTfaMessageTemplateWithHttpInfo($appId, $msgId);
        return $response;
    }

    /**
     * Operation getTfaMessageTemplateWithHttpInfo
     *
     * Get 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTfaMessageTemplateWithHttpInfo($appId, $msgId)
    {
        $request = $this->getTfaMessageTemplateRequest($appId, $msgId);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->getTfaMessageTemplateResponse($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->getTfaMessageTemplateApiException($e);
        }
    }

    /**
     * Operation getTfaMessageTemplateAsync
     *
     * Get 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaMessageTemplateAsync($appId, $msgId)
    {
        return $this->getTfaMessageTemplateAsyncWithHttpInfo($appId, $msgId)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getTfaMessageTemplateAsyncWithHttpInfo
     *
     * Get 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaMessageTemplateAsyncWithHttpInfo($appId, $msgId)
    {
        $request = $this->getTfaMessageTemplateRequest($appId, $msgId);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getTfaMessageTemplateResponse($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->getTfaMessageTemplateApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getTfaMessageTemplate'
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getTfaMessageTemplateRequest($appId, $msgId)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling getTfaMessageTemplate'
            );
        }
        // verify the required parameter 'msgId' is set
        if ($msgId === null || (is_array($msgId) && count($msgId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $msgId when calling getTfaMessageTemplate'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}/messages/{msgId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // 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 'getTfaMessageTemplate'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getTfaMessageTemplateResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaMessage',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation getTfaMessageTemplates
     *
     * Get 2FA message templates
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage[]
     */
    public function getTfaMessageTemplates($appId)
    {
        list($response) = $this->getTfaMessageTemplatesWithHttpInfo($appId);
        return $response;
    }

    /**
     * Operation getTfaMessageTemplatesWithHttpInfo
     *
     * Get 2FA message templates
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage[], HTTP status code, HTTP response headers (array of strings)
     */
    public function getTfaMessageTemplatesWithHttpInfo($appId)
    {
        $request = $this->getTfaMessageTemplatesRequest($appId);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->getTfaMessageTemplatesResponse($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->getTfaMessageTemplatesApiException($e);
        }
    }

    /**
     * Operation getTfaMessageTemplatesAsync
     *
     * Get 2FA message templates
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaMessageTemplatesAsync($appId)
    {
        return $this->getTfaMessageTemplatesAsyncWithHttpInfo($appId)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getTfaMessageTemplatesAsyncWithHttpInfo
     *
     * Get 2FA message templates
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaMessageTemplatesAsyncWithHttpInfo($appId)
    {
        $request = $this->getTfaMessageTemplatesRequest($appId);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getTfaMessageTemplatesResponse($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->getTfaMessageTemplatesApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getTfaMessageTemplates'
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getTfaMessageTemplatesRequest($appId)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling getTfaMessageTemplates'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}/messages';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // 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 'getTfaMessageTemplates'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage[]|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getTfaMessageTemplatesResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaMessage[]',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation getTfaVerificationStatus
     *
     * Get 2FA verification status
     *
     * @param  string $msisdn Filter by msisdn (phone number) for which verification status is checked. (required)
     * @param  string $appId ID of 2-FA application for which phone number verification status is requested. (required)
     * @param  bool $verified Filter by verified (true or false). (optional)
     * @param  bool $sent Filter by message sent status (true or false). (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerificationResponse
     */
    public function getTfaVerificationStatus($msisdn, $appId, $verified = null, $sent = null)
    {
        list($response) = $this->getTfaVerificationStatusWithHttpInfo($msisdn, $appId, $verified, $sent);
        return $response;
    }

    /**
     * Operation getTfaVerificationStatusWithHttpInfo
     *
     * Get 2FA verification status
     *
     * @param  string $msisdn Filter by msisdn (phone number) for which verification status is checked. (required)
     * @param  string $appId ID of 2-FA application for which phone number verification status is requested. (required)
     * @param  bool $verified Filter by verified (true or false). (optional)
     * @param  bool $sent Filter by message sent status (true or false). (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerificationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTfaVerificationStatusWithHttpInfo($msisdn, $appId, $verified = null, $sent = null)
    {
        $request = $this->getTfaVerificationStatusRequest($msisdn, $appId, $verified, $sent);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->getTfaVerificationStatusResponse($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->getTfaVerificationStatusApiException($e);
        }
    }

    /**
     * Operation getTfaVerificationStatusAsync
     *
     * Get 2FA verification status
     *
     * @param  string $msisdn Filter by msisdn (phone number) for which verification status is checked. (required)
     * @param  string $appId ID of 2-FA application for which phone number verification status is requested. (required)
     * @param  bool $verified Filter by verified (true or false). (optional)
     * @param  bool $sent Filter by message sent status (true or false). (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaVerificationStatusAsync($msisdn, $appId, $verified = null, $sent = null)
    {
        return $this->getTfaVerificationStatusAsyncWithHttpInfo($msisdn, $appId, $verified, $sent)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation getTfaVerificationStatusAsyncWithHttpInfo
     *
     * Get 2FA verification status
     *
     * @param  string $msisdn Filter by msisdn (phone number) for which verification status is checked. (required)
     * @param  string $appId ID of 2-FA application for which phone number verification status is requested. (required)
     * @param  bool $verified Filter by verified (true or false). (optional)
     * @param  bool $sent Filter by message sent status (true or false). (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTfaVerificationStatusAsyncWithHttpInfo($msisdn, $appId, $verified = null, $sent = null)
    {
        $request = $this->getTfaVerificationStatusRequest($msisdn, $appId, $verified, $sent);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->getTfaVerificationStatusResponse($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->getTfaVerificationStatusApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'getTfaVerificationStatus'
     *
     * @param  string $msisdn Filter by msisdn (phone number) for which verification status is checked. (required)
     * @param  string $appId ID of 2-FA application for which phone number verification status is requested. (required)
     * @param  bool $verified Filter by verified (true or false). (optional)
     * @param  bool $sent Filter by message sent status (true or false). (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function getTfaVerificationStatusRequest($msisdn, $appId, $verified = null, $sent = null)
    {
        // verify the required parameter 'msisdn' is set
        if ($msisdn === null || (is_array($msisdn) && count($msisdn) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $msisdn when calling getTfaVerificationStatus'
            );
        }
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling getTfaVerificationStatus'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}/verifications';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';

        // query params
        if ($msisdn !== null) {
            $queryParams['msisdn'] = $msisdn;
        }
        // query params
        if ($verified !== null) {
            $queryParams['verified'] = $verified;
        }
        // query params
        if ($sent !== null) {
            $queryParams['sent'] = $sent;
        }


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


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

        // 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 'getTfaVerificationStatus'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerificationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function getTfaVerificationStatusResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaVerificationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation resendTfaPinCodeOverSms
     *
     * Resend 2FA PIN code over SMS
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest tfaResendPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse
     */
    public function resendTfaPinCodeOverSms($pinId, $tfaResendPinRequest = null)
    {
        list($response) = $this->resendTfaPinCodeOverSmsWithHttpInfo($pinId, $tfaResendPinRequest);
        return $response;
    }

    /**
     * Operation resendTfaPinCodeOverSmsWithHttpInfo
     *
     * Resend 2FA PIN code over SMS
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function resendTfaPinCodeOverSmsWithHttpInfo($pinId, $tfaResendPinRequest = null)
    {
        $request = $this->resendTfaPinCodeOverSmsRequest($pinId, $tfaResendPinRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->resendTfaPinCodeOverSmsResponse($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->resendTfaPinCodeOverSmsApiException($e);
        }
    }

    /**
     * Operation resendTfaPinCodeOverSmsAsync
     *
     * Resend 2FA PIN code over SMS
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function resendTfaPinCodeOverSmsAsync($pinId, $tfaResendPinRequest = null)
    {
        return $this->resendTfaPinCodeOverSmsAsyncWithHttpInfo($pinId, $tfaResendPinRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation resendTfaPinCodeOverSmsAsyncWithHttpInfo
     *
     * Resend 2FA PIN code over SMS
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function resendTfaPinCodeOverSmsAsyncWithHttpInfo($pinId, $tfaResendPinRequest = null)
    {
        $request = $this->resendTfaPinCodeOverSmsRequest($pinId, $tfaResendPinRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->resendTfaPinCodeOverSmsResponse($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->resendTfaPinCodeOverSmsApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'resendTfaPinCodeOverSms'
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function resendTfaPinCodeOverSmsRequest($pinId, $tfaResendPinRequest = null)
    {
        // verify the required parameter 'pinId' is set
        if ($pinId === null || (is_array($pinId) && count($pinId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $pinId when calling resendTfaPinCodeOverSms'
            );
        }

        $resourcePath = '/2fa/2/pin/{pinId}/resend';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaResendPinRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaResendPinRequest));
            } else {
                $httpBody = $tfaResendPinRequest;
            }
        } elseif (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 'resendTfaPinCodeOverSms'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function resendTfaPinCodeOverSmsResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaStartAuthenticationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation resendTfaPinCodeOverVoice
     *
     * Resend 2FA PIN code over Voice
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest tfaResendPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse
     */
    public function resendTfaPinCodeOverVoice($pinId, $tfaResendPinRequest = null)
    {
        list($response) = $this->resendTfaPinCodeOverVoiceWithHttpInfo($pinId, $tfaResendPinRequest);
        return $response;
    }

    /**
     * Operation resendTfaPinCodeOverVoiceWithHttpInfo
     *
     * Resend 2FA PIN code over Voice
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function resendTfaPinCodeOverVoiceWithHttpInfo($pinId, $tfaResendPinRequest = null)
    {
        $request = $this->resendTfaPinCodeOverVoiceRequest($pinId, $tfaResendPinRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->resendTfaPinCodeOverVoiceResponse($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->resendTfaPinCodeOverVoiceApiException($e);
        }
    }

    /**
     * Operation resendTfaPinCodeOverVoiceAsync
     *
     * Resend 2FA PIN code over Voice
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function resendTfaPinCodeOverVoiceAsync($pinId, $tfaResendPinRequest = null)
    {
        return $this->resendTfaPinCodeOverVoiceAsyncWithHttpInfo($pinId, $tfaResendPinRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation resendTfaPinCodeOverVoiceAsyncWithHttpInfo
     *
     * Resend 2FA PIN code over Voice
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function resendTfaPinCodeOverVoiceAsyncWithHttpInfo($pinId, $tfaResendPinRequest = null)
    {
        $request = $this->resendTfaPinCodeOverVoiceRequest($pinId, $tfaResendPinRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->resendTfaPinCodeOverVoiceResponse($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->resendTfaPinCodeOverVoiceApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'resendTfaPinCodeOverVoice'
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaResendPinRequest $tfaResendPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function resendTfaPinCodeOverVoiceRequest($pinId, $tfaResendPinRequest = null)
    {
        // verify the required parameter 'pinId' is set
        if ($pinId === null || (is_array($pinId) && count($pinId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $pinId when calling resendTfaPinCodeOverVoice'
            );
        }

        $resourcePath = '/2fa/2/pin/{pinId}/resend/voice';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaResendPinRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaResendPinRequest));
            } else {
                $httpBody = $tfaResendPinRequest;
            }
        } elseif (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 'resendTfaPinCodeOverVoice'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function resendTfaPinCodeOverVoiceResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaStartAuthenticationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation sendTfaPinCodeOverSms
     *
     * Send 2FA PIN code over SMS
     *
     * @param  bool $ncNeeded Indicates if Number Lookup is needed before sending the 2FA message. If the parameter value is true, Number Lookup will be requested before sending the SMS. If the value is false, the SMS will be sent without requesting Number Lookup. Field&#39;s default value is &#x60;true&#x60;. (optional)
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest tfaStartAuthenticationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse
     */
    public function sendTfaPinCodeOverSms($ncNeeded = null, $tfaStartAuthenticationRequest = null)
    {
        list($response) = $this->sendTfaPinCodeOverSmsWithHttpInfo($ncNeeded, $tfaStartAuthenticationRequest);
        return $response;
    }

    /**
     * Operation sendTfaPinCodeOverSmsWithHttpInfo
     *
     * Send 2FA PIN code over SMS
     *
     * @param  bool $ncNeeded Indicates if Number Lookup is needed before sending the 2FA message. If the parameter value is true, Number Lookup will be requested before sending the SMS. If the value is false, the SMS will be sent without requesting Number Lookup. Field&#39;s default value is &#x60;true&#x60;. (optional)
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function sendTfaPinCodeOverSmsWithHttpInfo($ncNeeded = null, $tfaStartAuthenticationRequest = null)
    {
        $request = $this->sendTfaPinCodeOverSmsRequest($ncNeeded, $tfaStartAuthenticationRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->sendTfaPinCodeOverSmsResponse($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->sendTfaPinCodeOverSmsApiException($e);
        }
    }

    /**
     * Operation sendTfaPinCodeOverSmsAsync
     *
     * Send 2FA PIN code over SMS
     *
     * @param  bool $ncNeeded Indicates if Number Lookup is needed before sending the 2FA message. If the parameter value is true, Number Lookup will be requested before sending the SMS. If the value is false, the SMS will be sent without requesting Number Lookup. Field&#39;s default value is &#x60;true&#x60;. (optional)
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendTfaPinCodeOverSmsAsync($ncNeeded = null, $tfaStartAuthenticationRequest = null)
    {
        return $this->sendTfaPinCodeOverSmsAsyncWithHttpInfo($ncNeeded, $tfaStartAuthenticationRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation sendTfaPinCodeOverSmsAsyncWithHttpInfo
     *
     * Send 2FA PIN code over SMS
     *
     * @param  bool $ncNeeded Indicates if Number Lookup is needed before sending the 2FA message. If the parameter value is true, Number Lookup will be requested before sending the SMS. If the value is false, the SMS will be sent without requesting Number Lookup. Field&#39;s default value is &#x60;true&#x60;. (optional)
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendTfaPinCodeOverSmsAsyncWithHttpInfo($ncNeeded = null, $tfaStartAuthenticationRequest = null)
    {
        $request = $this->sendTfaPinCodeOverSmsRequest($ncNeeded, $tfaStartAuthenticationRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->sendTfaPinCodeOverSmsResponse($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->sendTfaPinCodeOverSmsApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'sendTfaPinCodeOverSms'
     *
     * @param  bool $ncNeeded Indicates if Number Lookup is needed before sending the 2FA message. If the parameter value is true, Number Lookup will be requested before sending the SMS. If the value is false, the SMS will be sent without requesting Number Lookup. Field&#39;s default value is &#x60;true&#x60;. (optional)
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function sendTfaPinCodeOverSmsRequest($ncNeeded = null, $tfaStartAuthenticationRequest = null)
    {
        $resourcePath = '/2fa/2/pin';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';

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




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

        // for model (json/xml)
        if (isset($tfaStartAuthenticationRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaStartAuthenticationRequest));
            } else {
                $httpBody = $tfaStartAuthenticationRequest;
            }
        } elseif (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 'sendTfaPinCodeOverSms'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function sendTfaPinCodeOverSmsResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaStartAuthenticationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation sendTfaPinCodeOverVoice
     *
     * Send 2FA PIN code over Voice
     *
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest tfaStartAuthenticationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse
     */
    public function sendTfaPinCodeOverVoice($tfaStartAuthenticationRequest = null)
    {
        list($response) = $this->sendTfaPinCodeOverVoiceWithHttpInfo($tfaStartAuthenticationRequest);
        return $response;
    }

    /**
     * Operation sendTfaPinCodeOverVoiceWithHttpInfo
     *
     * Send 2FA PIN code over Voice
     *
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function sendTfaPinCodeOverVoiceWithHttpInfo($tfaStartAuthenticationRequest = null)
    {
        $request = $this->sendTfaPinCodeOverVoiceRequest($tfaStartAuthenticationRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->sendTfaPinCodeOverVoiceResponse($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->sendTfaPinCodeOverVoiceApiException($e);
        }
    }

    /**
     * Operation sendTfaPinCodeOverVoiceAsync
     *
     * Send 2FA PIN code over Voice
     *
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendTfaPinCodeOverVoiceAsync($tfaStartAuthenticationRequest = null)
    {
        return $this->sendTfaPinCodeOverVoiceAsyncWithHttpInfo($tfaStartAuthenticationRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation sendTfaPinCodeOverVoiceAsyncWithHttpInfo
     *
     * Send 2FA PIN code over Voice
     *
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function sendTfaPinCodeOverVoiceAsyncWithHttpInfo($tfaStartAuthenticationRequest = null)
    {
        $request = $this->sendTfaPinCodeOverVoiceRequest($tfaStartAuthenticationRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->sendTfaPinCodeOverVoiceResponse($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->sendTfaPinCodeOverVoiceApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'sendTfaPinCodeOverVoice'
     *
     * @param  \Infobip\Model\TfaStartAuthenticationRequest $tfaStartAuthenticationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function sendTfaPinCodeOverVoiceRequest($tfaStartAuthenticationRequest = null)
    {
        $resourcePath = '/2fa/2/pin/voice';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';





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

        // for model (json/xml)
        if (isset($tfaStartAuthenticationRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaStartAuthenticationRequest));
            } else {
                $httpBody = $tfaStartAuthenticationRequest;
            }
        } elseif (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 'sendTfaPinCodeOverVoice'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaStartAuthenticationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function sendTfaPinCodeOverVoiceResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaStartAuthenticationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation updateTfaApplication
     *
     * Update 2FA application
     *
     * @param  string $appId ID of application that should be updated. (required)
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest tfaApplicationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse
     */
    public function updateTfaApplication($appId, $tfaApplicationRequest = null)
    {
        list($response) = $this->updateTfaApplicationWithHttpInfo($appId, $tfaApplicationRequest);
        return $response;
    }

    /**
     * Operation updateTfaApplicationWithHttpInfo
     *
     * Update 2FA application
     *
     * @param  string $appId ID of application that should be updated. (required)
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateTfaApplicationWithHttpInfo($appId, $tfaApplicationRequest = null)
    {
        $request = $this->updateTfaApplicationRequest($appId, $tfaApplicationRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->updateTfaApplicationResponse($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->updateTfaApplicationApiException($e);
        }
    }

    /**
     * Operation updateTfaApplicationAsync
     *
     * Update 2FA application
     *
     * @param  string $appId ID of application that should be updated. (required)
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateTfaApplicationAsync($appId, $tfaApplicationRequest = null)
    {
        return $this->updateTfaApplicationAsyncWithHttpInfo($appId, $tfaApplicationRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation updateTfaApplicationAsyncWithHttpInfo
     *
     * Update 2FA application
     *
     * @param  string $appId ID of application that should be updated. (required)
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateTfaApplicationAsyncWithHttpInfo($appId, $tfaApplicationRequest = null)
    {
        $request = $this->updateTfaApplicationRequest($appId, $tfaApplicationRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->updateTfaApplicationResponse($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->updateTfaApplicationApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'updateTfaApplication'
     *
     * @param  string $appId ID of application that should be updated. (required)
     * @param  \Infobip\Model\TfaApplicationRequest $tfaApplicationRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function updateTfaApplicationRequest($appId, $tfaApplicationRequest = null)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling updateTfaApplication'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaApplicationRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaApplicationRequest));
            } else {
                $httpBody = $tfaApplicationRequest;
            }
        } elseif (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(
            'PUT',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create response for operation 'updateTfaApplication'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaApplicationResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function updateTfaApplicationResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaApplicationResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation updateTfaMessageTemplate
     *
     * Update 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     * @param  \Infobip\Model\TfaUpdateMessageRequest $tfaUpdateMessageRequest tfaUpdateMessageRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage
     */
    public function updateTfaMessageTemplate($appId, $msgId, $tfaUpdateMessageRequest = null)
    {
        list($response) = $this->updateTfaMessageTemplateWithHttpInfo($appId, $msgId, $tfaUpdateMessageRequest);
        return $response;
    }

    /**
     * Operation updateTfaMessageTemplateWithHttpInfo
     *
     * Update 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     * @param  \Infobip\Model\TfaUpdateMessageRequest $tfaUpdateMessageRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateTfaMessageTemplateWithHttpInfo($appId, $msgId, $tfaUpdateMessageRequest = null)
    {
        $request = $this->updateTfaMessageTemplateRequest($appId, $msgId, $tfaUpdateMessageRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->updateTfaMessageTemplateResponse($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->updateTfaMessageTemplateApiException($e);
        }
    }

    /**
     * Operation updateTfaMessageTemplateAsync
     *
     * Update 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     * @param  \Infobip\Model\TfaUpdateMessageRequest $tfaUpdateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateTfaMessageTemplateAsync($appId, $msgId, $tfaUpdateMessageRequest = null)
    {
        return $this->updateTfaMessageTemplateAsyncWithHttpInfo($appId, $msgId, $tfaUpdateMessageRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation updateTfaMessageTemplateAsyncWithHttpInfo
     *
     * Update 2FA message template
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     * @param  \Infobip\Model\TfaUpdateMessageRequest $tfaUpdateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateTfaMessageTemplateAsyncWithHttpInfo($appId, $msgId, $tfaUpdateMessageRequest = null)
    {
        $request = $this->updateTfaMessageTemplateRequest($appId, $msgId, $tfaUpdateMessageRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->updateTfaMessageTemplateResponse($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->updateTfaMessageTemplateApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'updateTfaMessageTemplate'
     *
     * @param  string $appId ID of application for which requested message was created. (required)
     * @param  string $msgId Requested message ID. (required)
     * @param  \Infobip\Model\TfaUpdateMessageRequest $tfaUpdateMessageRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function updateTfaMessageTemplateRequest($appId, $msgId, $tfaUpdateMessageRequest = null)
    {
        // verify the required parameter 'appId' is set
        if ($appId === null || (is_array($appId) && count($appId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $appId when calling updateTfaMessageTemplate'
            );
        }
        // verify the required parameter 'msgId' is set
        if ($msgId === null || (is_array($msgId) && count($msgId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $msgId when calling updateTfaMessageTemplate'
            );
        }

        $resourcePath = '/2fa/2/applications/{appId}/messages/{msgId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaUpdateMessageRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaUpdateMessageRequest));
            } else {
                $httpBody = $tfaUpdateMessageRequest;
            }
        } elseif (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(
            'PUT',
            $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Create response for operation 'updateTfaMessageTemplate'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaMessage|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function updateTfaMessageTemplateResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaMessage',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        return $apiException;
    }

    /**
     * Operation verifyTfaPhoneNumber
     *
     * Verify phone number
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaVerifyPinRequest $tfaVerifyPinRequest tfaVerifyPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerifyPinResponse
     */
    public function verifyTfaPhoneNumber($pinId, $tfaVerifyPinRequest = null)
    {
        list($response) = $this->verifyTfaPhoneNumberWithHttpInfo($pinId, $tfaVerifyPinRequest);
        return $response;
    }

    /**
     * Operation verifyTfaPhoneNumberWithHttpInfo
     *
     * Verify phone number
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaVerifyPinRequest $tfaVerifyPinRequest (optional)
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerifyPinResponse, HTTP status code, HTTP response headers (array of strings)
     */
    public function verifyTfaPhoneNumberWithHttpInfo($pinId, $tfaVerifyPinRequest = null)
    {
        $request = $this->verifyTfaPhoneNumberRequest($pinId, $tfaVerifyPinRequest);

        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
                return $this->verifyTfaPhoneNumberResponse($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->verifyTfaPhoneNumberApiException($e);
        }
    }

    /**
     * Operation verifyTfaPhoneNumberAsync
     *
     * Verify phone number
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaVerifyPinRequest $tfaVerifyPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function verifyTfaPhoneNumberAsync($pinId, $tfaVerifyPinRequest = null)
    {
        return $this->verifyTfaPhoneNumberAsyncWithHttpInfo($pinId, $tfaVerifyPinRequest)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }

    /**
     * Operation verifyTfaPhoneNumberAsyncWithHttpInfo
     *
     * Verify phone number
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaVerifyPinRequest $tfaVerifyPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function verifyTfaPhoneNumberAsyncWithHttpInfo($pinId, $tfaVerifyPinRequest = null)
    {
        $request = $this->verifyTfaPhoneNumberRequest($pinId, $tfaVerifyPinRequest);

        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($request) {
                    return $this->verifyTfaPhoneNumberResponse($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->verifyTfaPhoneNumberApiException($e);
                }
            );
    }

    /**
     * Create request for operation 'verifyTfaPhoneNumber'
     *
     * @param  string $pinId ID of the pin code that has to be verified. (required)
     * @param  \Infobip\Model\TfaVerifyPinRequest $tfaVerifyPinRequest (optional)
     *
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request
     */
    protected function verifyTfaPhoneNumberRequest($pinId, $tfaVerifyPinRequest = null)
    {
        // verify the required parameter 'pinId' is set
        if ($pinId === null || (is_array($pinId) && count($pinId) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $pinId when calling verifyTfaPhoneNumber'
            );
        }

        $resourcePath = '/2fa/2/pin/{pinId}/verify';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';



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


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

        // for model (json/xml)
        if (isset($tfaVerifyPinRequest)) {
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($tfaVerifyPinRequest));
            } else {
                $httpBody = $tfaVerifyPinRequest;
            }
        } elseif (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 'verifyTfaPhoneNumber'
     *
     * @param \GuzzleHttp\Psr7\Response $response
     * @param string $requestUri
     *
     * @throws \Infobip\ApiException on non-2xx response
     * @return array of \Infobip\Model\TfaApiException|\Infobip\Model\TfaApiException|\Infobip\Model\TfaVerifyPinResponse|null, HTTP status code, HTTP response headers (array of strings)
     */
    protected function verifyTfaPhoneNumberResponse($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;


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

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

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

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

        $data = ObjectSerializer::deserialize(
            $apiException->getResponseBody(),
            '\Infobip\Model\TfaVerifyPinResponse',
            $apiException->getResponseHeaders()
        );
        $apiException->setResponseObject($data);
        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;
    }
}
