package {{package}}

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._

{{#imports}}import {{import}}
{{/imports}}

{{#operations}}
object {{classname}} {

  val client = PooledHttp1Client()

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

  {{#operation}}
  def {{nickname}}(host: String{{#allParams}}{{#-first}}, {{/-first}}{{paramName}}: {{dataType}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}){{#queryParams}}{{#-first}}(implicit {{/-first}}{{paramName}}Query: QueryParam[{{dataType}}]{{^-last}}, {{/-last}}{{#-last}}){{/-last}}{{/queryParams}}: {{>operationReturnType}}{{#returnType}}    implicit val returnTypeDecoder: EntityDecoder[{{returnType}}] = jsonOf[{{returnType}}]

{{/returnType}}
    val path = "{{path}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}",escape({{paramName}}.toString)){{/pathParams}}

    val httpMethod = Method.{{httpMethod}}
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      {{#headerParams}}Header("{{baseName}}", {{paramName}}){{^-last}}, {{/-last}}{{/headerParams}})
    val queryParams = Query(
      {{#queryParams}}("{{paramName}}", Some({{baseName}}Query.toParamString({{baseName}}))){{^-last}}, {{/-last}}{{/queryParams}})

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(host + path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType)){{#bodyParam}}.withBody({{paramName}}){{/bodyParam}}
      {{>clientFunction}}
    } yield resp
  }

  {{/operation}}
}

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

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

  {{#operation}}
  def {{nickname}}({{#allParams}}{{paramName}}: {{dataType}}{{#defaultValue}} = {{{.}}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}){{#queryParams}}{{#-first}}(implicit {{/-first}}{{paramName}}Query: QueryParam[{{dataType}}]{{^-last}}, {{/-last}}{{#-last}}){{/-last}}{{/queryParams}}: {{>operationReturnType}}{{#returnType}}    implicit val returnTypeDecoder: EntityDecoder[{{returnType}}] = jsonOf[{{returnType}}]

{{/returnType}}
    val path = "{{path}}"{{#pathParams}}.replaceAll("\\{" + "{{baseName}}" + "\\}",escape({{paramName}}.toString)){{/pathParams}}

    val httpMethod = Method.{{httpMethod}}
    val contentType = `Content-Type`(MediaType.`application/json`)
    val headers = Headers(
      {{#headerParams}}Header("{{baseName}}", {{paramName}}){{^-last}}, {{/-last}}{{/headerParams}})
    val queryParams = Query(
      {{#queryParams}}("{{paramName}}", Some({{baseName}}Query.toParamString({{baseName}}))){{^-last}}, {{/-last}}{{/queryParams}})

    for {
      uri           <- Task.fromDisjunction(Uri.fromString(path))
      uriWithParams =  uri.copy(query = queryParams)
      req           =  Request(method = httpMethod, uri = uriWithParams, headers = headers.put(contentType)){{#bodyParam}}.withBody({{paramName}}){{/bodyParam}}
      {{>clientFunction}}
    } yield resp
  }

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