{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}

{{#operations}}
module {{package}}.{{classname}} (
      {{#operation}}{{operationId}}{{#hasMore}}
    , {{/hasMore}}{{/operation}}
    , proxy{{classname}}
    , {{classname}}
    ) where
{{/operations}}

import GHC.Generics
import Data.Proxy
import Servant.API
import Servant.Client
import Network.URI (URI (..), URIAuth (..), parseURI)
import Data.Maybe (fromMaybe)
import Servant.Common.Text
import Data.List (intercalate)
import qualified Data.Text as T
import Utils
import Test.QuickCheck
{{#imports}}import {{import}}
{{/imports}}

{{#operations}}
{{#operation}}
{{#hasFormParams}}
data Form{{#formParams}}{{baseName}}{{/formParams}} = Form{{#formParams}}{{baseName}}{{/formParams}}
    { {{#formParams}}{{baseName}} :: {{dataType}}{{#hasMore}}
    , {{/hasMore}}{{/formParams}}
    } deriving (Show, Eq, Generic)

instance FromFormUrlEncoded Form{{#formParams}}{{baseName}}{{/formParams}} where
    fromFormUrlEncoded inputs = Form{{#formParams}}{{baseName}}{{/formParams}} <$> {{#formParams}} lkp inputs "{{baseName}}"{{#hasMore}} <*> {{/hasMore}}{{/formParams}}
instance ToFormUrlEncoded Form{{#formParams}}{{baseName}}{{/formParams}} where
    toFormUrlEncoded x = [({{#formParams}}(T.pack $ show $ {{package}}.{{classname}}.{{baseName}} x){{#hasMore}}, {{/hasMore}}{{/formParams}})]
instance Arbitrary Form{{#formParams}}{{baseName}}{{/formParams}} where
    arbitrary = Form{{#formParams}}{{baseName}}{{/formParams}} <$> {{#formParams}}arbitrary{{#hasMore}} <*> {{/hasMore}}{{/formParams}}
{{/hasFormParams}}

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

{{#operations}}
type {{classname}} = {{#operation}}{{& nickname}} -- {{operationId}}{{#hasMore}}
    :<|> {{/hasMore}}{{/operation}}
{{/operations}}

proxy{{classname}} :: Proxy {{classname}}
proxy{{classname}} = Proxy

{{#operations}}

serverPath :: String
serverPath = "{{basePath}}"

parseHostPort :: String -> (String, Int)
parseHostPort path = (host,port)
    where
        authority = case parseURI path of
            Just x -> uriAuthority x
            _      -> Nothing
        (host, port) = case authority of
            Just y -> (uriRegName y, (getPort . uriPort) y)
            _      -> ("localhost", 8080)
        getPort p = case (length p) of
            0 -> 80
            _ -> (read . drop 1) p

(host, port) = parseHostPort serverPath

{{#operation}}
{{operationId}}{{#hasMore}}
    :<|> {{/hasMore}}{{/operation}}
    = client proxy{{classname}} $ BaseUrl Http host port
{{/operations}}
