package {{apiImplPackage}};

{{>frag/imports}}
{{>hooks/apiImplHeader}}
{{>generatedAnnotation}}
public class {{className name}}ApiImpl implements {{@root/apiPackage}}.{{className name}}Api {

	{{>hooks/injectApi group=. name='api'}}
	private {{apiSpiPackage}}.ApiAuthorizationProvider authorizationProvider;

	{{>hooks/apiImplClassBody}}
{{#each operations}}
	{{>frag/operationVars op=. jaxrs=false}}
	@Override
	public {{#if returnNativeType}}{{{returnNativeType}}}{{else}}void{{/if}} {{identifier name}}({{{_parameters}}}){{#each (nonDefaultResponses)}}{{#if @first}} throws{{else}},{{/if}} {{#each (responseContentAndNone)}}{{#unless @first}}, {{/unless}}{{{className (concat ../../name '_' ../code)}}}{{#unless @first}}{{className content.mediaType.mediaType}}{{/unless}}Exception{{/each}}{{/each}} {
		{{#if securityRequirements}}
		if (authorizationProvider != null) {
			authorizationProvider.authorize(this);
		}

		{{/if}}
		{{#ifeq requestBody.defaultContent.encoding.type 'MULTIPART'}}
		{{>frag/operationVars op=. jaxrs=false requestBodyVar='__multipartBody'}}
		java.util.ArrayList<org.apache.cxf.jaxrs.ext.multipart.Attachment> __multipartBodyParts = new java.util.ArrayList<>();
		{{#each requestBody.defaultContent.encoding.properties}}
		{{#set '__propertyVar'}}
		{{identifier ../requestBody.name}}.{{getter property}}()
		{{/set}}
		if ({{{__propertyVar}}} != null) {
			{{#if (isArray property)}}
			// property {{{property.name}}}, nullable {{{property.nullable}}}, native type {{{property.nativeType}}}
			// component nullable {{{property.schema.component.nullable}}}, native type {{property.schema.component.nativeType.componentType}}
			{{#if property.nullable}}
			if ({{{__propertyVar}}}.isPresent()) {
				for ({{{property.schema.component.nativeType.componentType}}} __anObject : {{{__propertyVar}}}.get()) {
					{{>frag/multipartProperty . propertyVar='__anObject' bodyPartsVar='__multipartBodyParts' content=../requestBody.defaultContent schemaUsage=property.schema.component}}
				}
			}
			{{else}}
			for ({{{property.schema.component.nativeType.componentType}}} __anObject : {{{__propertyVar}}}) {
				{{>frag/multipartProperty . propertyVar='__anObject' bodyPartsVar='__multipartBodyParts' content=../requestBody.defaultContent schemaUsage=property.schema.component}}
			}
			{{/if}}
			{{else}}
			{{>frag/multipartProperty . propertyVar=__propertyVar bodyPartsVar='__multipartBodyParts' content=../requestBody.defaultContent schemaUsage=property}}
			{{/if}}
		}
		{{/each}}
		org.apache.cxf.jaxrs.ext.multipart.MultipartBody __multipartBody = new org.apache.cxf.jaxrs.ext.multipart.MultipartBody(
			__multipartBodyParts,
			javax.ws.rs.core.MediaType.valueOf({{{stringLiteral requestBody.defaultContent.mediaType.mediaType}}}),
			true
		);

		{{/ifeq}}
		try {
			{{#if securityRequirements}}
			try {
				{{#if returnNativeType}}return {{/if}}api.{{identifier name}}({{{_arguments}}});
			} catch ({{javax}}.ws.rs.WebApplicationException __e) {
				if (__e.getResponse().getStatus() == 401 && authorizationProvider != null) {
					if (authorizationProvider.reauthorize(this, __e.getResponse())) {
						{{#if returnNativeType}}return {{/if}}api.{{identifier name}}({{{_arguments}}});
					}
				}
				throw __e;
			}
			{{else}}
			{{#if returnNativeType}}return {{/if}}api.{{identifier name}}({{{_arguments}}});
			{{/if}}
		} catch ({{javax}}.ws.rs.WebApplicationException __e) {
			{{#each (nonDefaultAndCatchAllResponses)}}
			if (__e.getResponse().getStatus() == {{code}}) {
				try {
					{{#each contents}}
					if (__e.getResponse().getMediaType().isCompatible({{javax}}.ws.rs.core.MediaType.valueOf({{{stringLiteral mediaType.mediaType}}}))) {
						throw new {{className (concat ../../name '_' ../code)}}{{#unless @first}}{{className mediaType.mediaType}}{{/unless}}Exception({{#if nativeType}}__e.getResponse().readEntity({{{nativeType.literalType}}}.class){{/if}});
					}
					{{/each}}

					throw new {{@root/apiPackage}}.UnprocessableResponseException(__e.getResponse(), new {{javax}}.ws.rs.ProcessingException("Unsupported media type for response status " + __e.getResponse().getStatus() + ": " + __e.getResponse().getMediaType()));
				} catch ({{javax}}.ws.rs.ProcessingException __processingException) {
					throw new {{@root/apiPackage}}.UnprocessableResponseException(__e.getResponse(), __processingException);
				}
			}
			{{/each}}
			{{#if catchAllResponse}}
			/* Catch-all response */
			{{#with catchAllResponse}}
			try {
				{{#each contents}}
				if (__e.getResponse().getMediaType().isCompatible({{javax}}.ws.rs.core.MediaType.valueOf({{{stringLiteral mediaType.mediaType}}}))) {
					throw new {{className (concat ../../name '_' ../code)}}{{#unless @first}}{{className mediaType.mediaType}}{{/unless}}Exception({{#if nativeType}}__e.getResponse().readEntity({{{nativeType.literalType}}}.class){{/if}});
				}
				{{/each}}

				throw new {{@root/apiPackage}}.UnprocessableResponseException(__e.getResponse(), new {{javax}}.ws.rs.ProcessingException("Unsupported media type for response status " + __e.getResponse().getStatus() + ": " + __e.getResponse().getMediaType()));
			} catch ({{javax}}.ws.rs.ProcessingException __processingException) {
				throw new {{@root/apiPackage}}.UnprocessableResponseException(__e.getResponse(), __processingException);
			}
			{{/with}}
			{{else}}
			throw new {{@root/apiPackage}}.UnexpectedResponseException(__e.getResponse(), __e);
			{{/if}}
		} catch ({{javax}}.ws.rs.client.ResponseProcessingException __e) {
			throw new {{@root/apiPackage}}.UnprocessableResponseException(__e.getResponse(), __e);
		} catch ({{javax}}.ws.rs.ProcessingException __e) {
			if (__e.getCause() instanceof java.net.SocketTimeoutException) {
				throw new {{@root/apiPackage}}.UnexpectedTimeoutException((java.net.SocketTimeoutException) __e.getCause());
			}
			throw new {{@root/apiPackage}}.UnexpectedApiException(
				__e.getMessage() != null
					? __e.getMessage()
					: __e.getCause() != null && __e.getCause().getMessage() != null
						? __e.getCause().getMessage()
						: __e.toString()
			);
		}
	}
	
{{/each}}
	public {{apiSpiPackage}}.ApiAuthorizationProvider getAuthorizationProvider() {
		return authorizationProvider;
	}

	public void setAuthorizationProvider({{apiSpiPackage}}.ApiAuthorizationProvider authorizationProvider) {
		this.authorizationProvider = authorizationProvider;
	}

}
