/**
 * Scala Client API Integration Test
 * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen)
 *
 * OpenAPI spec version: 1
 * 
 *
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen.git
 * Do not edit the class manually.
 */

package io.swagger.client.api

import java.text.SimpleDateFormat

import io.swagger.client.model.Person
import io.swagger.client.{ApiInvoker, 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 java.util.TimeZone

import scala.collection.mutable.HashMap

import com.wordnik.swagger.client._
import scala.concurrent.Future
import collection.mutable

import java.net.URI

import com.wordnik.swagger.client.ClientResponseReaders.Json4sFormatsReader._
import com.wordnik.swagger.client.RequestWriters.Json4sFormatsWriter._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.concurrent.duration._
import scala.util.{Failure, Success, Try}

import org.json4s._

class PeopleApi(
  val defBasePath: String = "https://localhost:8080",
  defApiInvoker: ApiInvoker = ApiInvoker
) {
  private lazy val dateTimeFormatter = {
    val formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"))
    formatter
  }
  private val dateFormatter = {
    val formatter = new SimpleDateFormat("yyyy-MM-dd")
    formatter.setTimeZone(TimeZone.getTimeZone("UTC"))
    formatter
  }
  implicit val formats = new org.json4s.DefaultFormats {
    override def dateFormatter = dateTimeFormatter
  }
  implicit val stringReader: ClientResponseReader[String] = ClientResponseReaders.StringReader
  implicit val unitReader: ClientResponseReader[Unit] = ClientResponseReaders.UnitReader
  implicit val jvalueReader: ClientResponseReader[JValue] = ClientResponseReaders.JValueReader
  implicit val jsonReader: ClientResponseReader[Nothing] = JsonFormatsReader
  implicit val stringWriter: RequestWriter[String] = RequestWriters.StringWriter
  implicit val jsonWriter: RequestWriter[Nothing] = JsonFormatsWriter

  var basePath: String = defBasePath
  var apiInvoker: ApiInvoker = defApiInvoker

  def addHeader(key: String, value: String): mutable.HashMap[String, String] = {
    apiInvoker.defaultHeaders += key -> value
  }

  val config: SwaggerConfig = SwaggerConfig.forUrl(new URI(defBasePath))
  val client = new RestClient(config)
  val helper = new PeopleApiAsyncHelper(client, config)

  /**
   * People listing
   * 
   *
   * @param age Limit results to people of a certain age. (optional)
   * @return List[Person]
   */
  def getPeople(age: Option[Long] = None): Option[List[Person]] = {
    val await = Try(Await.result(getPeopleAsync(age), Duration.Inf))
    await match {
      case Success(i) => Some(await.get)
      case Failure(t) => None
    }
  }

  /**
   * People listing asynchronously
   * 
   *
   * @param age Limit results to people of a certain age. (optional)
   * @return Future(List[Person])
   */
  def getPeopleAsync(age: Option[Long] = None): Future[List[Person]] = {
      helper.getPeople(age)
  }

  /**
   * get people by id
   * Retrieves a single person record by personId
   *
   * @param personId The person&#39;s ID. 
   * @return Person
   */
  def getPersonById(personId: Long): Option[Person] = {
    val await = Try(Await.result(getPersonByIdAsync(personId), Duration.Inf))
    await match {
      case Success(i) => Some(await.get)
      case Failure(t) => None
    }
  }

  /**
   * get people by id asynchronously
   * Retrieves a single person record by personId
   *
   * @param personId The person&#39;s ID. 
   * @return Future(Person)
   */
  def getPersonByIdAsync(personId: Long): Future[Person] = {
      helper.getPersonById(personId)
  }

  /**
   * People batch save
   * 
   *
   * @param body Batch input of people to save 
   * @param size Explicitly sets the batch size (optional, default to 25)
   * @return List[Person]
   */
  def savePeople(body: List[Person], size: Option[Integer] = Option(25)): Option[List[Person]] = {
    val await = Try(Await.result(savePeopleAsync(body, size), Duration.Inf))
    await match {
      case Success(i) => Some(await.get)
      case Failure(t) => None
    }
  }

  /**
   * People batch save asynchronously
   * 
   *
   * @param body Batch input of people to save 
   * @param size Explicitly sets the batch size (optional, default to 25)
   * @return Future(List[Person])
   */
  def savePeopleAsync(body: List[Person], size: Option[Integer] = Option(25)): Future[List[Person]] = {
      helper.savePeople(body, size)
  }

}

class PeopleApiAsyncHelper(client: TransportClient, config: SwaggerConfig) extends ApiClient(client, config) {

  def getPeople(age: Option[Long] = None
    )(implicit reader: ClientResponseReader[List[Person]]): Future[List[Person]] = {
    // create path and map variables
    val path = (addFmt("/people"))

    // query params
    val queryParams = new mutable.HashMap[String, String]
    val headerParams = new mutable.HashMap[String, String]

    age match {
      case Some(param) => queryParams += "age" -> param.toString
      case _ => queryParams
    }

    val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "")
    resFuture flatMap { resp =>
      process(reader.read(resp))
    }
  }

  def getPersonById(personId: Long)(implicit reader: ClientResponseReader[Person]): Future[Person] = {
    // create path and map variables
    val path = (addFmt("/people/{personId}")
      replaceAll("\\{" + "personId" + "\\}", personId.toString))

    // query params
    val queryParams = new mutable.HashMap[String, String]
    val headerParams = new mutable.HashMap[String, String]


    val resFuture = client.submit("GET", path, queryParams.toMap, headerParams.toMap, "")
    resFuture flatMap { resp =>
      process(reader.read(resp))
    }
  }

  def savePeople(body: List[Person],
    size: Option[Integer] = Option(25)
    )(implicit reader: ClientResponseReader[List[Person]], writer: RequestWriter[List[Person]]): Future[List[Person]] = {
    // create path and map variables
    val path = (addFmt("/people"))

    // query params
    val queryParams = new mutable.HashMap[String, String]
    val headerParams = new mutable.HashMap[String, String]

    if (body == null) throw new Exception("Missing required parameter 'body' when calling PeopleApi->savePeople")
    size match {
      case Some(param) => queryParams += "size" -> param.toString
      case _ => queryParams
    }

    val resFuture = client.submit("POST", path, queryParams.toMap, headerParams.toMap, writer.write(body))
    resFuture flatMap { resp =>
      process(reader.read(resp))
    }
  }


}
