package org.openapitools.client.api

import argonaut._
import argonaut.EncodeJson._
import argonaut.DecodeJson._

import java.io.File
import java.net.URLEncoder
import java.util.UUID

import org.http4s._
import org.http4s.{EntityDecoder, EntityEncoder}
import org.http4s.argonaut._
import org.http4s.client._
import org.http4s.client.blaze.PooledHttp1Client
import org.http4s.headers._

import org.joda.time.DateTime

import scalaz.concurrent.Task

import HelperCodecs._

import org.openapitools.client.api.Order

object StoreApi {

  val client = PooledHttp1Client()

  def escape(value: String): String = URLEncoder.encode(value, "utf-8").replaceAll("\\+", "%20")

  def deleteOrder(host: String, orderId: String): Task[Unit] = {
    val path = "/store/order/{orderId}".replaceAll("\\{" + "orderId" + "\\}",escape(orderId.toString))
    
    val httpMethod = Method.DELETE
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(host + path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.fetch[Unit](req)(_ => Task.now(()))

    } yield resp
  }
  
  def getInventory(host: String): Task[Map[String, Integer]] = {
    implicit val returnTypeDecoder: EntityDecoder[Map[String, Integer]] = jsonOf[Map[String, Integer]]

    val path = "/store/inventory"
    
    val httpMethod = Method.GET
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(host + path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.expect[Map[String, Integer]](req)

    } yield resp
  }
  
  def getOrderById(host: String, orderId: Long): Task[Order] = {
    implicit val returnTypeDecoder: EntityDecoder[Order] = jsonOf[Order]

    val path = "/store/order/{orderId}".replaceAll("\\{" + "orderId" + "\\}",escape(orderId.toString))
    
    val httpMethod = Method.GET
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(host + path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.expect[Order](req)

    } yield resp
  }
  
  def placeOrder(host: String, order: Order): Task[Order] = {
    implicit val returnTypeDecoder: EntityDecoder[Order] = jsonOf[Order]

    val path = "/store/order"
    
    val httpMethod = Method.POST
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(host + path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType)).withBody(order)
      resp          <- client.expect[Order](req)

    } yield resp
  }
  
}

class HttpServiceStoreApi(service: HttpService) {
  val client = Client.fromHttpService(service)

  def escape(value: String): String = URLEncoder.encode(value, "utf-8").replaceAll("\\+", "%20")

  def deleteOrder(orderId: String): Task[Unit] = {
    val path = "/store/order/{orderId}".replaceAll("\\{" + "orderId" + "\\}",escape(orderId.toString))
    
    val httpMethod = Method.DELETE
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.fetch[Unit](req)(_ => Task.now(()))

    } yield resp
  }
  
  def getInventory(): Task[Map[String, Integer]] = {
    implicit val returnTypeDecoder: EntityDecoder[Map[String, Integer]] = jsonOf[Map[String, Integer]]

    val path = "/store/inventory"
    
    val httpMethod = Method.GET
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.expect[Map[String, Integer]](req)

    } yield resp
  }
  
  def getOrderById(orderId: Long): Task[Order] = {
    implicit val returnTypeDecoder: EntityDecoder[Order] = jsonOf[Order]

    val path = "/store/order/{orderId}".replaceAll("\\{" + "orderId" + "\\}",escape(orderId.toString))
    
    val httpMethod = Method.GET
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType))
      resp          <- client.expect[Order](req)

    } yield resp
  }
  
  def placeOrder(order: Order): Task[Order] = {
    implicit val returnTypeDecoder: EntityDecoder[Order] = jsonOf[Order]

    val path = "/store/order"
    
    val httpMethod = Method.POST
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      )
    val queryParams = Query(
      )

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType)).withBody(order)
      resp          <- client.expect[Order](req)

    } yield resp
  }
  
}
