{{>licenseInfo}}
package {{package}}

{{#imports}}import {{import}}
{{/imports}}
import {{invokerPackage}}.ApiInvoker
import {{invokerPackage}}.ApiException

import com.sun.jersey.multipart.FormDataMultiPart
import com.sun.jersey.multipart.file.FileDataBodyPart

import javax.ws.rs.core.MediaType

import java.io.File
import java.util.Date

import scala.collection.mutable.HashMap

{{#operations}}
class {{classname}}(val defBasePath: String = "{{basePath}}",
                        defApiInvoker: ApiInvoker = ApiInvoker) {
  var basePath = defBasePath
  var apiInvoker = defApiInvoker

  def addHeader(key: String, value: String) = apiInvoker.defaultHeaders += key -> value 

  {{#operation}}
  /**
   * {{summary}}
   * {{notes}}
{{#allParams}}   * @param {{paramName}} {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
{{/allParams}}   * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}}
   */
  def {{operationId}}({{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{#defaultValue}} /* = {{{defaultValue}}}*/{{/defaultValue}}{{/required}}{{^required}}Option[{{dataType}}]{{#defaultValue}} /* = {{{defaultValue}}}*/{{/defaultValue}}{{^defaultValue}} = None{{/defaultValue}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}}: Option[{{returnType}}]{{/returnType}} = {
    // create path and map variables
    val path = "{{path}}".replaceAll("\\{format\\}", "json"){{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}",apiInvoker.escape({{paramName}})){{/pathParams}}

    val contentTypes = List({{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}"application/json"{{/consumes}})
    val contentType = contentTypes(0)

    val queryParams = new HashMap[String, String]
    val headerParams = new HashMap[String, String]
    val formParams = new HashMap[String, String]

    {{#allParams}}
    {{#required}}
    {{^isPrimitiveType}}
    if ({{paramName}} == null) throw new Exception("Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}")

    {{/isPrimitiveType}}
    {{#isString}}
    if ({{paramName}} == null) throw new Exception("Missing required parameter '{{paramName}}' when calling {{classname}}->{{operationId}}")

    {{/isString}}
    {{/required}}
    {{/allParams}}
    {{#queryParams}}
    {{#required}}
    queryParams += "{{baseName}}" -> {{paramName}}.toString
    {{/required}}
    {{^required}}
    {{paramName}}.map(paramVal => queryParams += "{{baseName}}" -> paramVal.toString)
    {{/required}}
    {{/queryParams}}
    
    {{#headerParams}}
    {{#required}}
    headerParams += "{{baseName}}" -> {{paramName}}
    {{/required}}
    {{^required}}
    {{paramName}}.map(paramVal => headerParams += "{{baseName}}" -> paramVal)
    {{/required}}
    {{/headerParams}}

    var postBody: AnyRef = {{#bodyParam}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}.map(paramVal => paramVal){{/required}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}}

    if (contentType.startsWith("multipart/form-data")) {
      val mp = new FormDataMultiPart
      {{#formParams}}
      {{#notFile}}
      {{#required}}
      mp.field("{{baseName}}", {{paramName}}.toString, MediaType.MULTIPART_FORM_DATA_TYPE)
      {{/required}}
      {{^required}}
      {{paramName}}.map(paramVal => mp.field("{{baseName}}", paramVal.toString, MediaType.MULTIPART_FORM_DATA_TYPE))
      {{/required}}
      {{/notFile}}
      {{#isFile}}
      {{#required}}
      mp.field("{{baseName}}", file.getName)
      mp.bodyPart(new FileDataBodyPart("{{baseName}}", {{paramName}}, MediaType.MULTIPART_FORM_DATA_TYPE))
      {{/required}}
      {{^required}}
      file.map(fileVal => mp.field("{{baseName}}", fileVal.getName))
      {{paramName}}.map(paramVal => mp.bodyPart(new FileDataBodyPart("{{baseName}}", paramVal, MediaType.MULTIPART_FORM_DATA_TYPE)))
      {{/required}}
      {{/isFile}}
      {{/formParams}}
      postBody = mp
    } else {
      {{#formParams}}
      {{#notFile}}
      {{#required}}
      formParams += "{{baseName}}" -> {{paramName}}.toString
      {{/required}}
      {{^required}}
      {{paramName}}.map(paramVal => formParams += "{{baseName}}" -> paramVal.toString)
      {{/required}}
      {{/notFile}}
      {{/formParams}}
    }

    try {
      apiInvoker.invokeApi(basePath, path, "{{httpMethod}}", queryParams.toMap, formParams.toMap, postBody, headerParams.toMap, contentType) match {
        case s: String =>
          {{#returnType}} Some(apiInvoker.deserialize(s, "{{returnContainer}}", classOf[{{returnBaseType}}]).asInstanceOf[{{returnType}}])
        {{/returnType}} 
        case _ => None
      }
    } catch {
      case ex: ApiException if ex.code == 404 => None
      case ex: ApiException => throw ex
    }
  }

  {{/operation}}
}
{{/operations}}
