<?php
/**
 * ProjectApi
 * PHP version 5
 *
 * @category Class
 * @package  XeroAPI\XeroPHP Project
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */

/**
 * Xero Projects API
 *
 * This is the Xero Projects API
 *
 * OpenAPI spec version: 2.10.4
 * Contact: api@xero.com
 * Generated by: https://openapi-generator.tech
 * OpenAPI Generator version: 4.3.1
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

namespace XeroAPI\XeroPHP\Api;

use GuzzleHttp\Client;
use GuzzleHttp\ClientInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\MultipartStream;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\RequestOptions;
use XeroAPI\XeroPHP\ApiException;
use XeroAPI\XeroPHP\Configuration;
use XeroAPI\XeroPHP\HeaderSelector;
use XeroAPI\XeroPHP\ProjectObjectSerializer;

/**
 * ProjectApi Class Doc Comment
 *
 * @category Class
 * @package  XeroAPI\XeroPHP
 * @author   OpenAPI Generator team
 * @link     https://openapi-generator.tech
 */
class ProjectApi
{
    /**
     * @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 createProject
     * Create one or more new projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Create a new project with ProjectCreateOrUpdate object (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\Project|\XeroAPI\XeroPHP\Models\Project\Error
     */
    public function createProject($xero_tenant_id, $project_create_or_update)
    {
        list($response) = $this->createProjectWithHttpInfo($xero_tenant_id, $project_create_or_update);
        return $response;
    }
    /**
     * Operation createProjectWithHttpInfo
     * Create one or more new projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Create a new project with ProjectCreateOrUpdate object (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\Project|\XeroAPI\XeroPHP\Models\Project\Error, HTTP status code, HTTP response headers (array of strings)
     */
    public function createProjectWithHttpInfo($xero_tenant_id, $project_create_or_update)
    {
        $request = $this->createProjectRequest($xero_tenant_id, $project_create_or_update);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 201:
                    if ('\XeroAPI\XeroPHP\Models\Project\Project' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Project', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                case 400:
                    if ('\XeroAPI\XeroPHP\Models\Project\Error' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Error', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\Project';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 201:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Project',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation createProjectAsync
     * Create one or more new projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Create a new project with ProjectCreateOrUpdate object (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createProjectAsync($xero_tenant_id, $project_create_or_update)
    {
        return $this->createProjectAsyncWithHttpInfo($xero_tenant_id, $project_create_or_update)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation createProjectAsyncWithHttpInfo
     * Create one or more new projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Create a new project with ProjectCreateOrUpdate object (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function createProjectAsyncWithHttpInfo($xero_tenant_id, $project_create_or_update)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\Project';
        $request = $this->createProjectRequest($xero_tenant_id, $project_create_or_update);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'createProject'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Create a new project with ProjectCreateOrUpdate object (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function createProjectRequest($xero_tenant_id, $project_create_or_update)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling createProject'
            );
        }
        // verify the required parameter 'project_create_or_update' is set
        if ($project_create_or_update === null || (is_array($project_create_or_update) && count($project_create_or_update) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_create_or_update when calling createProject'
            );
        }
        $resourcePath = '/Projects';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // body params
        $_tempBody = null;
        if (isset($project_create_or_update)) {
            $_tempBody = $project_create_or_update;
        }
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'POST',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation createTimeEntry
     * Creates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are creating (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\TimeEntry
     */
    public function createTimeEntry($xero_tenant_id, $project_id, $time_entry_create_or_update)
    {
        list($response) = $this->createTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_create_or_update);
        return $response;
    }
    /**
     * Operation createTimeEntryWithHttpInfo
     * Creates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are creating (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\TimeEntry, HTTP status code, HTTP response headers (array of strings)
     */
    public function createTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_create_or_update)
    {
        $request = $this->createTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_create_or_update);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\TimeEntry' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\TimeEntry', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntry';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\TimeEntry',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation createTimeEntryAsync
     * Creates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are creating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function createTimeEntryAsync($xero_tenant_id, $project_id, $time_entry_create_or_update)
    {
        return $this->createTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_create_or_update)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation createTimeEntryAsyncWithHttpInfo
     * Creates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are creating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function createTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_create_or_update)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntry';
        $request = $this->createTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_create_or_update);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'createTimeEntry'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are creating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function createTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_create_or_update)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling createTimeEntry'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling createTimeEntry'
            );
        }
        // verify the required parameter 'time_entry_create_or_update' is set
        if ($time_entry_create_or_update === null || (is_array($time_entry_create_or_update) && count($time_entry_create_or_update) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $time_entry_create_or_update when calling createTimeEntry'
            );
        }
        $resourcePath = '/Projects/{projectId}/Time';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if (isset($time_entry_create_or_update)) {
            $_tempBody = $time_entry_create_or_update;
        }
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'POST',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation deleteTimeEntry
     * Deletes a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual task by appending the id to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return void
     */
    public function deleteTimeEntry($xero_tenant_id, $project_id, $time_entry_id)
    {
        $this->deleteTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id);
    }
    /**
     * Operation deleteTimeEntryWithHttpInfo
     * Deletes a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual task by appending the id to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of null, HTTP status code, HTTP response headers (array of strings)
     */
    public function deleteTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
    {
        $request = $this->deleteTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            return [null, $statusCode, $response->getHeaders()];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
            }
            throw $e;
        }
    }
    /**
     * Operation deleteTimeEntryAsync
     * Deletes a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual task by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function deleteTimeEntryAsync($xero_tenant_id, $project_id, $time_entry_id)
    {
        return $this->deleteTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation deleteTimeEntryAsyncWithHttpInfo
     * Deletes a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual task by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function deleteTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
    {
        $returnType = '';
        $request = $this->deleteTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    return [null, $response->getStatusCode(), $response->getHeaders()];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'deleteTimeEntry'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual task by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function deleteTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling deleteTimeEntry'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling deleteTimeEntry'
            );
        }
        // verify the required parameter 'time_entry_id' is set
        if ($time_entry_id === null || (is_array($time_entry_id) && count($time_entry_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $time_entry_id when calling deleteTimeEntry'
            );
        }
        $resourcePath = '/Projects/{projectId}/Time/{timeEntryId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // path params
        if ($time_entry_id !== null) {
            $resourcePath = str_replace(
                '{' . 'timeEntryId' . '}',
                ProjectObjectSerializer::toPathValue($time_entry_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                []
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                [],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'DELETE',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getProject
     * Retrieves a single project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\Project|\XeroAPI\XeroPHP\Models\Project\Error
     */
    public function getProject($xero_tenant_id, $project_id)
    {
        list($response) = $this->getProjectWithHttpInfo($xero_tenant_id, $project_id);
        return $response;
    }
    /**
     * Operation getProjectWithHttpInfo
     * Retrieves a single project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\Project|\XeroAPI\XeroPHP\Models\Project\Error, HTTP status code, HTTP response headers (array of strings)
     */
    public function getProjectWithHttpInfo($xero_tenant_id, $project_id)
    {
        $request = $this->getProjectRequest($xero_tenant_id, $project_id);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\Project' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Project', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                case 400:
                    if ('\XeroAPI\XeroPHP\Models\Project\Error' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Error', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\Project';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Project',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getProjectAsync
     * Retrieves a single project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getProjectAsync($xero_tenant_id, $project_id)
    {
        return $this->getProjectAsyncWithHttpInfo($xero_tenant_id, $project_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getProjectAsyncWithHttpInfo
     * Retrieves a single project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getProjectAsyncWithHttpInfo($xero_tenant_id, $project_id)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\Project';
        $request = $this->getProjectRequest($xero_tenant_id, $project_id);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getProject'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getProjectRequest($xero_tenant_id, $project_id)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getProject'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling getProject'
            );
        }
        $resourcePath = '/Projects/{projectId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getProjectUsers
     * Retrieves a list of all project users
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\ProjectUsers|\XeroAPI\XeroPHP\Models\Project\Error
     */
    public function getProjectUsers($xero_tenant_id, $page = 1, $page_size = 50)
    {
        list($response) = $this->getProjectUsersWithHttpInfo($xero_tenant_id, $page, $page_size);
        return $response;
    }
    /**
     * Operation getProjectUsersWithHttpInfo
     * Retrieves a list of all project users
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\ProjectUsers|\XeroAPI\XeroPHP\Models\Project\Error, HTTP status code, HTTP response headers (array of strings)
     */
    public function getProjectUsersWithHttpInfo($xero_tenant_id, $page = 1, $page_size = 50)
    {
        $request = $this->getProjectUsersRequest($xero_tenant_id, $page, $page_size);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\ProjectUsers' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\ProjectUsers', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                case 400:
                    if ('\XeroAPI\XeroPHP\Models\Project\Error' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Error', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\ProjectUsers';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\ProjectUsers',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getProjectUsersAsync
     * Retrieves a list of all project users
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getProjectUsersAsync($xero_tenant_id, $page = 1, $page_size = 50)
    {
        return $this->getProjectUsersAsyncWithHttpInfo($xero_tenant_id, $page, $page_size)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getProjectUsersAsyncWithHttpInfo
     * Retrieves a list of all project users
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getProjectUsersAsyncWithHttpInfo($xero_tenant_id, $page = 1, $page_size = 50)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\ProjectUsers';
        $request = $this->getProjectUsersRequest($xero_tenant_id, $page, $page_size);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getProjectUsers'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getProjectUsersRequest($xero_tenant_id, $page = 1, $page_size = 50)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getProjectUsers'
            );
        }
        if ($page_size !== null && $page_size > 500) {
            throw new \InvalidArgumentException('invalid value for "$page_size" when calling ProjectApi.getProjectUsers, must be smaller than or equal to 500.');
        }
        if ($page_size !== null && $page_size < 1) {
            throw new \InvalidArgumentException('invalid value for "$page_size" when calling ProjectApi.getProjectUsers, must be bigger than or equal to 1.');
        }

        $resourcePath = '/ProjectsUsers';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // query params
        if ($page !== null) {
            $queryParams['page'] = ProjectObjectSerializer::toQueryValue($page);
        }
        // query params
        if ($page_size !== null) {
            $queryParams['pageSize'] = ProjectObjectSerializer::toQueryValue($page_size);
        }
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getProjects
     * Retrieves all projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string[] $project_ids Search for all projects that match a comma separated list of projectIds (optional)
     * @param  string $contact_id Filter for projects for a specific contact (optional)
     * @param  string $states Filter for projects in a particular state (INPROGRESS or CLOSED) (optional)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\Projects|\XeroAPI\XeroPHP\Models\Project\Error
     */
    public function getProjects($xero_tenant_id, $project_ids = null, $contact_id = null, $states = null, $page = 1, $page_size = 50)
    {
        list($response) = $this->getProjectsWithHttpInfo($xero_tenant_id, $project_ids, $contact_id, $states, $page, $page_size);
        return $response;
    }
    /**
     * Operation getProjectsWithHttpInfo
     * Retrieves all projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string[] $project_ids Search for all projects that match a comma separated list of projectIds (optional)
     * @param  string $contact_id Filter for projects for a specific contact (optional)
     * @param  string $states Filter for projects in a particular state (INPROGRESS or CLOSED) (optional)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\Projects|\XeroAPI\XeroPHP\Models\Project\Error, HTTP status code, HTTP response headers (array of strings)
     */
    public function getProjectsWithHttpInfo($xero_tenant_id, $project_ids = null, $contact_id = null, $states = null, $page = 1, $page_size = 50)
    {
        $request = $this->getProjectsRequest($xero_tenant_id, $project_ids, $contact_id, $states, $page, $page_size);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\Projects' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Projects', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                case 400:
                    if ('\XeroAPI\XeroPHP\Models\Project\Error' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Error', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\Projects';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Projects',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getProjectsAsync
     * Retrieves all projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string[] $project_ids Search for all projects that match a comma separated list of projectIds (optional)
     * @param  string $contact_id Filter for projects for a specific contact (optional)
     * @param  string $states Filter for projects in a particular state (INPROGRESS or CLOSED) (optional)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getProjectsAsync($xero_tenant_id, $project_ids = null, $contact_id = null, $states = null, $page = 1, $page_size = 50)
    {
        return $this->getProjectsAsyncWithHttpInfo($xero_tenant_id, $project_ids, $contact_id, $states, $page, $page_size)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getProjectsAsyncWithHttpInfo
     * Retrieves all projects
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string[] $project_ids Search for all projects that match a comma separated list of projectIds (optional)
     * @param  string $contact_id Filter for projects for a specific contact (optional)
     * @param  string $states Filter for projects in a particular state (INPROGRESS or CLOSED) (optional)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getProjectsAsyncWithHttpInfo($xero_tenant_id, $project_ids = null, $contact_id = null, $states = null, $page = 1, $page_size = 50)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\Projects';
        $request = $this->getProjectsRequest($xero_tenant_id, $project_ids, $contact_id, $states, $page, $page_size);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getProjects'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string[] $project_ids Search for all projects that match a comma separated list of projectIds (optional)
     * @param  string $contact_id Filter for projects for a specific contact (optional)
     * @param  string $states Filter for projects in a particular state (INPROGRESS or CLOSED) (optional)
     * @param  int $page set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional, default to 1)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional, default to 50)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getProjectsRequest($xero_tenant_id, $project_ids = null, $contact_id = null, $states = null, $page = 1, $page_size = 50)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getProjects'
            );
        }
        if ($page_size !== null && $page_size > 500) {
            throw new \InvalidArgumentException('invalid value for "$page_size" when calling ProjectApi.getProjects, must be smaller than or equal to 500.');
        }
        if ($page_size !== null && $page_size < 1) {
            throw new \InvalidArgumentException('invalid value for "$page_size" when calling ProjectApi.getProjects, must be bigger than or equal to 1.');
        }

        $resourcePath = '/Projects';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // query params
        if (is_array($project_ids)) {
            $project_ids = ProjectObjectSerializer::serializeCollection($project_ids, 'multi', true);
        }
        if ($project_ids !== null) {
            $queryParams['projectIds'] = ProjectObjectSerializer::toQueryValue($project_ids);
        }
        // query params
        if ($contact_id !== null) {
            $queryParams['contactID'] = ProjectObjectSerializer::toQueryValue($contact_id);
        }
        // query params
        if ($states !== null) {
            $queryParams['states'] = ProjectObjectSerializer::toQueryValue($states);
        }
        // query params
        if ($page !== null) {
            $queryParams['page'] = ProjectObjectSerializer::toQueryValue($page);
        }
        // query params
        if ($page_size !== null) {
            $queryParams['pageSize'] = ProjectObjectSerializer::toQueryValue($page_size);
        }
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getTask
     * Retrieves a single project task
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $task_id You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID} (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\Task
     */
    public function getTask($xero_tenant_id, $project_id, $task_id)
    {
        list($response) = $this->getTaskWithHttpInfo($xero_tenant_id, $project_id, $task_id);
        return $response;
    }
    /**
     * Operation getTaskWithHttpInfo
     * Retrieves a single project task
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $task_id You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID} (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\Task, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTaskWithHttpInfo($xero_tenant_id, $project_id, $task_id)
    {
        $request = $this->getTaskRequest($xero_tenant_id, $project_id, $task_id);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\Task' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Task', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\Task';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Task',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getTaskAsync
     * Retrieves a single project task
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $task_id You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID} (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTaskAsync($xero_tenant_id, $project_id, $task_id)
    {
        return $this->getTaskAsyncWithHttpInfo($xero_tenant_id, $project_id, $task_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getTaskAsyncWithHttpInfo
     * Retrieves a single project task
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $task_id You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID} (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getTaskAsyncWithHttpInfo($xero_tenant_id, $project_id, $task_id)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\Task';
        $request = $this->getTaskRequest($xero_tenant_id, $project_id, $task_id);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getTask'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $task_id You can specify an individual task by appending the taskId to the endpoint, i.e. GET https://.../tasks/{taskID} (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getTaskRequest($xero_tenant_id, $project_id, $task_id)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getTask'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling getTask'
            );
        }
        // verify the required parameter 'task_id' is set
        if ($task_id === null || (is_array($task_id) && count($task_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $task_id when calling getTask'
            );
        }
        $resourcePath = '/Projects/{projectId}/Tasks/{taskId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // path params
        if ($task_id !== null) {
            $resourcePath = str_replace(
                '{' . 'taskId' . '}',
                ProjectObjectSerializer::toPathValue($task_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getTasks
     * Retrieves all project tasks
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string $task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID} (optional)
     * @param  \XeroAPI\XeroPHP\Models\Project\ChargeType $charge_type charge_type (optional)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\Tasks
     */
    public function getTasks($xero_tenant_id, $project_id, $page = null, $page_size = null, $task_ids = null, $charge_type = null)
    {
        list($response) = $this->getTasksWithHttpInfo($xero_tenant_id, $project_id, $page, $page_size, $task_ids, $charge_type);
        return $response;
    }
    /**
     * Operation getTasksWithHttpInfo
     * Retrieves all project tasks
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string $task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID} (optional)
     * @param  \XeroAPI\XeroPHP\Models\Project\ChargeType $charge_type (optional)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\Tasks, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTasksWithHttpInfo($xero_tenant_id, $project_id, $page = null, $page_size = null, $task_ids = null, $charge_type = null)
    {
        $request = $this->getTasksRequest($xero_tenant_id, $project_id, $page, $page_size, $task_ids, $charge_type);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\Tasks' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\Tasks', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\Tasks';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Tasks',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getTasksAsync
     * Retrieves all project tasks
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string $task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID} (optional)
     * @param  \XeroAPI\XeroPHP\Models\Project\ChargeType $charge_type (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTasksAsync($xero_tenant_id, $project_id, $page = null, $page_size = null, $task_ids = null, $charge_type = null)
    {
        return $this->getTasksAsyncWithHttpInfo($xero_tenant_id, $project_id, $page, $page_size, $task_ids, $charge_type)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getTasksAsyncWithHttpInfo
     * Retrieves all project tasks
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string $task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID} (optional)
     * @param  \XeroAPI\XeroPHP\Models\Project\ChargeType $charge_type (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getTasksAsyncWithHttpInfo($xero_tenant_id, $project_id, $page = null, $page_size = null, $task_ids = null, $charge_type = null)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\Tasks';
        $request = $this->getTasksRequest($xero_tenant_id, $project_id, $page, $page_size, $task_ids, $charge_type);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getTasks'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string $task_ids taskIdsSearch for all tasks that match a comma separated list of taskIds, i.e. GET https://.../tasks?taskIds&#x3D;{taskID},{taskID} (optional)
     * @param  \XeroAPI\XeroPHP\Models\Project\ChargeType $charge_type (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getTasksRequest($xero_tenant_id, $project_id, $page = null, $page_size = null, $task_ids = null, $charge_type = null)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getTasks'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling getTasks'
            );
        }
        $resourcePath = '/Projects/{projectId}/Tasks';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // query params
        if ($page !== null) {
            $queryParams['page'] = ProjectObjectSerializer::toQueryValue($page);
        }
        // query params
        if ($page_size !== null) {
            $queryParams['pageSize'] = ProjectObjectSerializer::toQueryValue($page_size);
        }
        // query params
        if ($task_ids !== null) {
            $queryParams['taskIds'] = ProjectObjectSerializer::toQueryValue($task_ids);
        }
        // query params
        if ($charge_type !== null) {
            $queryParams['chargeType'] = ProjectObjectSerializer::toQueryValue($charge_type);
        }
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getTimeEntries
     * Retrieves all time entries associated with a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id Identifier of the project, that the task (which the time entry is logged against) belongs to. (required)
     * @param  string $user_id The xero user identifier of the person who logged time. (optional)
     * @param  string $task_id Identifier of the task that time entry is logged against. (optional)
     * @param  string $invoice_id Finds all time entries for this invoice. (optional)
     * @param  string $contact_id Finds all time entries for this contact identifier. (optional)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string[] $states Comma-separated list of states to find. Will find all time entries that are in the status of whatever is specified. (optional)
     * @param  bool $is_chargeable Finds all time entries which relate to tasks with the charge type &#x60;TIME&#x60; or &#x60;FIXED&#x60;. (optional)
     * @param  \DateTime $date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @param  \DateTime $date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\TimeEntries
     */
    public function getTimeEntries($xero_tenant_id, $project_id, $user_id = null, $task_id = null, $invoice_id = null, $contact_id = null, $page = null, $page_size = null, $states = null, $is_chargeable = null, $date_after_utc = null, $date_before_utc = null)
    {
        list($response) = $this->getTimeEntriesWithHttpInfo($xero_tenant_id, $project_id, $user_id, $task_id, $invoice_id, $contact_id, $page, $page_size, $states, $is_chargeable, $date_after_utc, $date_before_utc);
        return $response;
    }
    /**
     * Operation getTimeEntriesWithHttpInfo
     * Retrieves all time entries associated with a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id Identifier of the project, that the task (which the time entry is logged against) belongs to. (required)
     * @param  string $user_id The xero user identifier of the person who logged time. (optional)
     * @param  string $task_id Identifier of the task that time entry is logged against. (optional)
     * @param  string $invoice_id Finds all time entries for this invoice. (optional)
     * @param  string $contact_id Finds all time entries for this contact identifier. (optional)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string[] $states Comma-separated list of states to find. Will find all time entries that are in the status of whatever is specified. (optional)
     * @param  bool $is_chargeable Finds all time entries which relate to tasks with the charge type &#x60;TIME&#x60; or &#x60;FIXED&#x60;. (optional)
     * @param  \DateTime $date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @param  \DateTime $date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\TimeEntries, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTimeEntriesWithHttpInfo($xero_tenant_id, $project_id, $user_id = null, $task_id = null, $invoice_id = null, $contact_id = null, $page = null, $page_size = null, $states = null, $is_chargeable = null, $date_after_utc = null, $date_before_utc = null)
    {
        $request = $this->getTimeEntriesRequest($xero_tenant_id, $project_id, $user_id, $task_id, $invoice_id, $contact_id, $page, $page_size, $states, $is_chargeable, $date_after_utc, $date_before_utc);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\TimeEntries' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\TimeEntries', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntries';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\TimeEntries',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getTimeEntriesAsync
     * Retrieves all time entries associated with a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id Identifier of the project, that the task (which the time entry is logged against) belongs to. (required)
     * @param  string $user_id The xero user identifier of the person who logged time. (optional)
     * @param  string $task_id Identifier of the task that time entry is logged against. (optional)
     * @param  string $invoice_id Finds all time entries for this invoice. (optional)
     * @param  string $contact_id Finds all time entries for this contact identifier. (optional)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string[] $states Comma-separated list of states to find. Will find all time entries that are in the status of whatever is specified. (optional)
     * @param  bool $is_chargeable Finds all time entries which relate to tasks with the charge type &#x60;TIME&#x60; or &#x60;FIXED&#x60;. (optional)
     * @param  \DateTime $date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @param  \DateTime $date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTimeEntriesAsync($xero_tenant_id, $project_id, $user_id = null, $task_id = null, $invoice_id = null, $contact_id = null, $page = null, $page_size = null, $states = null, $is_chargeable = null, $date_after_utc = null, $date_before_utc = null)
    {
        return $this->getTimeEntriesAsyncWithHttpInfo($xero_tenant_id, $project_id, $user_id, $task_id, $invoice_id, $contact_id, $page, $page_size, $states, $is_chargeable, $date_after_utc, $date_before_utc)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getTimeEntriesAsyncWithHttpInfo
     * Retrieves all time entries associated with a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id Identifier of the project, that the task (which the time entry is logged against) belongs to. (required)
     * @param  string $user_id The xero user identifier of the person who logged time. (optional)
     * @param  string $task_id Identifier of the task that time entry is logged against. (optional)
     * @param  string $invoice_id Finds all time entries for this invoice. (optional)
     * @param  string $contact_id Finds all time entries for this contact identifier. (optional)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string[] $states Comma-separated list of states to find. Will find all time entries that are in the status of whatever is specified. (optional)
     * @param  bool $is_chargeable Finds all time entries which relate to tasks with the charge type &#x60;TIME&#x60; or &#x60;FIXED&#x60;. (optional)
     * @param  \DateTime $date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @param  \DateTime $date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getTimeEntriesAsyncWithHttpInfo($xero_tenant_id, $project_id, $user_id = null, $task_id = null, $invoice_id = null, $contact_id = null, $page = null, $page_size = null, $states = null, $is_chargeable = null, $date_after_utc = null, $date_before_utc = null)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntries';
        $request = $this->getTimeEntriesRequest($xero_tenant_id, $project_id, $user_id, $task_id, $invoice_id, $contact_id, $page, $page_size, $states, $is_chargeable, $date_after_utc, $date_before_utc);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getTimeEntries'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id Identifier of the project, that the task (which the time entry is logged against) belongs to. (required)
     * @param  string $user_id The xero user identifier of the person who logged time. (optional)
     * @param  string $task_id Identifier of the task that time entry is logged against. (optional)
     * @param  string $invoice_id Finds all time entries for this invoice. (optional)
     * @param  string $contact_id Finds all time entries for this contact identifier. (optional)
     * @param  int $page Set to 1 by default. The requested number of the page in paged response - Must be a number greater than 0. (optional)
     * @param  int $page_size Optional, it is set to 50 by default. The number of items to return per page in a paged response - Must be a number between 1 and 500. (optional)
     * @param  string[] $states Comma-separated list of states to find. Will find all time entries that are in the status of whatever is specified. (optional)
     * @param  bool $is_chargeable Finds all time entries which relate to tasks with the charge type &#x60;TIME&#x60; or &#x60;FIXED&#x60;. (optional)
     * @param  \DateTime $date_after_utc ISO 8601 UTC date. Finds all time entries on or after this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @param  \DateTime $date_before_utc ISO 8601 UTC date. Finds all time entries on or before this date filtered on the &#x60;dateUtc&#x60; field. (optional)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getTimeEntriesRequest($xero_tenant_id, $project_id, $user_id = null, $task_id = null, $invoice_id = null, $contact_id = null, $page = null, $page_size = null, $states = null, $is_chargeable = null, $date_after_utc = null, $date_before_utc = null)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getTimeEntries'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling getTimeEntries'
            );
        }
        $resourcePath = '/Projects/{projectId}/Time';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // query params
        if ($user_id !== null) {
            $queryParams['userId'] = ProjectObjectSerializer::toQueryValue($user_id);
        }
        // query params
        if ($task_id !== null) {
            $queryParams['taskId'] = ProjectObjectSerializer::toQueryValue($task_id);
        }
        // query params
        if ($invoice_id !== null) {
            $queryParams['invoiceId'] = ProjectObjectSerializer::toQueryValue($invoice_id);
        }
        // query params
        if ($contact_id !== null) {
            $queryParams['contactId'] = ProjectObjectSerializer::toQueryValue($contact_id);
        }
        // query params
        if ($page !== null) {
            $queryParams['page'] = ProjectObjectSerializer::toQueryValue($page);
        }
        // query params
        if ($page_size !== null) {
            $queryParams['pageSize'] = ProjectObjectSerializer::toQueryValue($page_size);
        }
        // query params
        if (is_array($states)) {
            $states = ProjectObjectSerializer::serializeCollection($states, 'multi', true);
        }
        if ($states !== null) {
            $queryParams['states'] = ProjectObjectSerializer::toQueryValue($states);
        }
        // query params
        if ($is_chargeable !== null) {
            $queryParams['isChargeable'] = $is_chargeable ? 'true' : 'false';
        }
        // query params
        if ($date_after_utc !== null) {
            $queryParams['dateAfterUtc'] = ProjectObjectSerializer::toQueryValue($date_after_utc);
        }
        // query params
        if ($date_before_utc !== null) {
            $queryParams['dateBeforeUtc'] = ProjectObjectSerializer::toQueryValue($date_before_utc);
        }
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation getTimeEntry
     * Retrieves a single time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return \XeroAPI\XeroPHP\Models\Project\TimeEntry
     */
    public function getTimeEntry($xero_tenant_id, $project_id, $time_entry_id)
    {
        list($response) = $this->getTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id);
        return $response;
    }
    /**
     * Operation getTimeEntryWithHttpInfo
     * Retrieves a single time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of \XeroAPI\XeroPHP\Models\Project\TimeEntry, HTTP status code, HTTP response headers (array of strings)
     */
    public function getTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
    {
        $request = $this->getTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            $responseBody = $response->getBody();
            switch($statusCode) {
                case 200:
                    if ('\XeroAPI\XeroPHP\Models\Project\TimeEntry' === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, '\XeroAPI\XeroPHP\Models\Project\TimeEntry', []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
            }
            $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntry';
            $responseBody = $response->getBody();
            if ($returnType === '\SplFileObject') {
                $content = $responseBody; //stream goes to serializer
            } else {
                $content = $responseBody->getContents();
            }
            return [
                ProjectObjectSerializer::deserialize($content, $returnType, []),
                $response->getStatusCode(),
                $response->getHeaders()
            ];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\TimeEntry',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation getTimeEntryAsync
     * Retrieves a single time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function getTimeEntryAsync($xero_tenant_id, $project_id, $time_entry_id)
    {
        return $this->getTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation getTimeEntryAsyncWithHttpInfo
     * Retrieves a single time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function getTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id)
    {
        $returnType = '\XeroAPI\XeroPHP\Models\Project\TimeEntry';
        $request = $this->getTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    $responseBody = $response->getBody();
                    if ($returnType === '\SplFileObject') {
                        $content = $responseBody; //stream goes to serializer
                    } else {
                        $content = $responseBody->getContents();
                    }
                    return [
                        ProjectObjectSerializer::deserialize($content, $returnType, []),
                        $response->getStatusCode(),
                        $response->getHeaders()
                    ];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'getTimeEntry'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function getTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling getTimeEntry'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling getTimeEntry'
            );
        }
        // verify the required parameter 'time_entry_id' is set
        if ($time_entry_id === null || (is_array($time_entry_id) && count($time_entry_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $time_entry_id when calling getTimeEntry'
            );
        }
        $resourcePath = '/Projects/{projectId}/Time/{timeEntryId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // path params
        if ($time_entry_id !== null) {
            $resourcePath = str_replace(
                '{' . 'timeEntryId' . '}',
                ProjectObjectSerializer::toPathValue($time_entry_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                []
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'GET',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation patchProject
     * creates a project for the specified contact
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectPatch $project_patch Update the status of an existing Project (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return void
     */
    public function patchProject($xero_tenant_id, $project_id, $project_patch)
    {
        $this->patchProjectWithHttpInfo($xero_tenant_id, $project_id, $project_patch);
    }
    /**
     * Operation patchProjectWithHttpInfo
     * creates a project for the specified contact
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectPatch $project_patch Update the status of an existing Project (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of null, HTTP status code, HTTP response headers (array of strings)
     */
    public function patchProjectWithHttpInfo($xero_tenant_id, $project_id, $project_patch)
    {
        $request = $this->patchProjectRequest($xero_tenant_id, $project_id, $project_patch);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            return [null, $statusCode, $response->getHeaders()];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation patchProjectAsync
     * creates a project for the specified contact
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectPatch $project_patch Update the status of an existing Project (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function patchProjectAsync($xero_tenant_id, $project_id, $project_patch)
    {
        return $this->patchProjectAsyncWithHttpInfo($xero_tenant_id, $project_id, $project_patch)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation patchProjectAsyncWithHttpInfo
     * creates a project for the specified contact
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectPatch $project_patch Update the status of an existing Project (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function patchProjectAsyncWithHttpInfo($xero_tenant_id, $project_id, $project_patch)
    {
        $returnType = '';
        $request = $this->patchProjectRequest($xero_tenant_id, $project_id, $project_patch);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    return [null, $response->getStatusCode(), $response->getHeaders()];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'patchProject'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectPatch $project_patch Update the status of an existing Project (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function patchProjectRequest($xero_tenant_id, $project_id, $project_patch)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling patchProject'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling patchProject'
            );
        }
        // verify the required parameter 'project_patch' is set
        if ($project_patch === null || (is_array($project_patch) && count($project_patch) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_patch when calling patchProject'
            );
        }
        $resourcePath = '/Projects/{projectId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if (isset($project_patch)) {
            $_tempBody = $project_patch;
        }
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'PATCH',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation updateProject
     * Updates a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Request of type ProjectCreateOrUpdate (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return void
     */
    public function updateProject($xero_tenant_id, $project_id, $project_create_or_update)
    {
        $this->updateProjectWithHttpInfo($xero_tenant_id, $project_id, $project_create_or_update);
    }
    /**
     * Operation updateProjectWithHttpInfo
     * Updates a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Request of type ProjectCreateOrUpdate (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of null, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateProjectWithHttpInfo($xero_tenant_id, $project_id, $project_create_or_update)
    {
        $request = $this->updateProjectRequest($xero_tenant_id, $project_id, $project_create_or_update);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            return [null, $statusCode, $response->getHeaders()];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 400:
                    $data = ProjectObjectSerializer::deserialize(
                        $e->getResponseBody(),
                        '\XeroAPI\XeroPHP\Models\Project\Error',
                        $e->getResponseHeaders()
                    );
                    $e->setResponseObject($data);
                    break;
            }
            throw $e;
        }
    }
    /**
     * Operation updateProjectAsync
     * Updates a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Request of type ProjectCreateOrUpdate (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateProjectAsync($xero_tenant_id, $project_id, $project_create_or_update)
    {
        return $this->updateProjectAsyncWithHttpInfo($xero_tenant_id, $project_id, $project_create_or_update)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation updateProjectAsyncWithHttpInfo
     * Updates a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Request of type ProjectCreateOrUpdate (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function updateProjectAsyncWithHttpInfo($xero_tenant_id, $project_id, $project_create_or_update)
    {
        $returnType = '';
        $request = $this->updateProjectRequest($xero_tenant_id, $project_id, $project_create_or_update);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    return [null, $response->getStatusCode(), $response->getHeaders()];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'updateProject'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\ProjectCreateOrUpdate $project_create_or_update Request of type ProjectCreateOrUpdate (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function updateProjectRequest($xero_tenant_id, $project_id, $project_create_or_update)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling updateProject'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling updateProject'
            );
        }
        // verify the required parameter 'project_create_or_update' is set
        if ($project_create_or_update === null || (is_array($project_create_or_update) && count($project_create_or_update) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_create_or_update when calling updateProject'
            );
        }
        $resourcePath = '/Projects/{projectId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if (isset($project_create_or_update)) {
            $_tempBody = $project_create_or_update;
        }
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                ['application/json']
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                ['application/json'],
                ['application/json']
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'PUT',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

    /**
     * Operation updateTimeEntry
     * Updates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are updating (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return void
     */
    public function updateTimeEntry($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
    {
        $this->updateTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update);
    }
    /**
     * Operation updateTimeEntryWithHttpInfo
     * Updates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are updating (required)
     * @throws \XeroAPI\XeroPHP\ApiException on non-2xx response
     * @throws \InvalidArgumentException
     * @return array of null, HTTP status code, HTTP response headers (array of strings)
     */
    public function updateTimeEntryWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
    {
        $request = $this->updateTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update);
        try {
            $options = $this->createHttpClientOption();
            try {
                $response = $this->client->send($request, $options);
            } catch (RequestException $e) {
                throw new ApiException(
                    "[{$e->getCode()}] {$e->getMessage()}",
                    $e->getCode(),
                    $e->getResponse() ? $e->getResponse()->getHeaders() : null,
                    $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null
                );
            }
            $statusCode = $response->getStatusCode();
            if ($statusCode < 200 || $statusCode > 299) {
                throw new ApiException(
                    sprintf(
                        '[%d] Error connecting to the API (%s)',
                        $statusCode,
                        $request->getUri()
                    ),
                    $statusCode,
                    $response->getHeaders(),
                    $response->getBody()
                );
            }
            return [null, $statusCode, $response->getHeaders()];
        } catch (ApiException $e) {
            switch ($e->getCode()) {
            }
            throw $e;
        }
    }
    /**
     * Operation updateTimeEntryAsync
     * Updates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are updating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface
     */
    public function updateTimeEntryAsync($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
    {
        return $this->updateTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
            ->then(
                function ($response) {
                    return $response[0];
                }
            );
    }
    /**
     * Operation updateTimeEntryAsyncWithHttpInfo
     * Updates a time entry for a specific project
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are updating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Promise\PromiseInterface */
    public function updateTimeEntryAsyncWithHttpInfo($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
    {
        $returnType = '';
        $request = $this->updateTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update);
        return $this->client
            ->sendAsync($request, $this->createHttpClientOption())
            ->then(
                function ($response) use ($returnType) {
                    return [null, $response->getStatusCode(), $response->getHeaders()];
                },
                function ($exception) {
                    $response = $exception->getResponse();
                    $statusCode = $response->getStatusCode();
                    throw new ApiException(
                        sprintf(
                            '[%d] Error connecting to the API (%s)',
                            $statusCode,
                            $exception->getRequest()->getUri()
                        ),
                        $statusCode,
                        $response->getHeaders(),
                        $response->getBody()
                    );
                }
            );
    }

    /**
     * Create request for operation 'updateTimeEntry'
     * @param  string $xero_tenant_id Xero identifier for Tenant (required)
     * @param  string $project_id You can specify an individual project by appending the projectId to the endpoint (required)
     * @param  string $time_entry_id You can specify an individual time entry by appending the id to the endpoint (required)
     * @param  \XeroAPI\XeroPHP\Models\Project\TimeEntryCreateOrUpdate $time_entry_create_or_update The time entry object you are updating (required)
     * @throws \InvalidArgumentException
     * @return \GuzzleHttp\Psr7\Request  */
    protected function updateTimeEntryRequest($xero_tenant_id, $project_id, $time_entry_id, $time_entry_create_or_update)
    {
        // verify the required parameter 'xero_tenant_id' is set
        if ($xero_tenant_id === null || (is_array($xero_tenant_id) && count($xero_tenant_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $xero_tenant_id when calling updateTimeEntry'
            );
        }
        // verify the required parameter 'project_id' is set
        if ($project_id === null || (is_array($project_id) && count($project_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $project_id when calling updateTimeEntry'
            );
        }
        // verify the required parameter 'time_entry_id' is set
        if ($time_entry_id === null || (is_array($time_entry_id) && count($time_entry_id) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $time_entry_id when calling updateTimeEntry'
            );
        }
        // verify the required parameter 'time_entry_create_or_update' is set
        if ($time_entry_create_or_update === null || (is_array($time_entry_create_or_update) && count($time_entry_create_or_update) === 0)) {
            throw new \InvalidArgumentException(
                'Missing the required parameter $time_entry_create_or_update when calling updateTimeEntry'
            );
        }
        $resourcePath = '/Projects/{projectId}/Time/{timeEntryId}';
        $formParams = [];
        $queryParams = [];
        $headerParams = [];
        $httpBody = '';
        $multipart = false;
        // header params
        if ($xero_tenant_id !== null) {
            $headerParams['Xero-Tenant-Id'] = ProjectObjectSerializer::toHeaderValue($xero_tenant_id);
        }
        // path params
        if ($project_id !== null) {
            $resourcePath = str_replace(
                '{' . 'projectId' . '}',
                ProjectObjectSerializer::toPathValue($project_id),
                $resourcePath
            );
        }
        // path params
        if ($time_entry_id !== null) {
            $resourcePath = str_replace(
                '{' . 'timeEntryId' . '}',
                ProjectObjectSerializer::toPathValue($time_entry_id),
                $resourcePath
            );
        }
        // body params
        $_tempBody = null;
        if (isset($time_entry_create_or_update)) {
            $_tempBody = $time_entry_create_or_update;
        }
        if ($multipart) {
            $headers = $this->headerSelector->selectHeadersForMultipart(
                []
            );
        } else {
            $headers = $this->headerSelector->selectHeaders(
                [],
                ['application/json']
            );
        }
        // for model (json/xml)
        if (isset($_tempBody)) {
            // $_tempBody is the method argument, if present
            if ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode(ProjectObjectSerializer::sanitizeForSerialization($_tempBody));
            } else {
                $httpBody = $_tempBody;
            }
        } elseif (count($formParams) > 0) {
            if ($multipart) {
                $multipartContents = [
                    [
                        'Content-type' => 'multipart/form-data',
                    ]
                ];
                
                // for HTTP post (form)
                $httpBody = new MultipartStream($multipartContents);

            } elseif ($headers['Content-Type'] === 'application/json') {
                $httpBody = \GuzzleHttp\json_encode($formParams);
            } else {
                // for HTTP post (form)
                $httpBody = \GuzzleHttp\Psr7\build_query($formParams);
            }
        }
        // this endpoint requires OAuth (access token)
        if ($this->config->getAccessToken() !== null) {
            $headers['Authorization'] = 'Bearer ' . $this->config->getAccessToken();
        }
        $defaultHeaders = [];
        if ($this->config->getUserAgent()) {
            $defaultHeaders['User-Agent'] = $this->config->getUserAgent();
        }
        $headers = array_merge(
            $defaultHeaders,
            $headerParams,
            $headers
        );
        $query = \GuzzleHttp\Psr7\build_query($queryParams);
        return new Request(
            'PUT',
            $this->config->getHostProject() . $resourcePath . ($query ? "?{$query}" : ''),
            $headers,
            $httpBody
        );
    }

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

        return $options;
    }
}
