{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

-- | This is a module containing an API with all `Servant.API` combinators. It
-- is used for testing only (in particular, checking that instances exist for
-- the core servant classes for each combinator).
module Servant.Test.ComprehensiveAPI where

import Data.Proxy (Proxy (..))

import Servant.API
import Servant.Types.SourceT (SourceT)

type GET = Get '[JSON] NoContent

type ComprehensiveAPI =
  ComprehensiveAPIWithoutStreamingOrRaw'
    (EmptyEndpoint :<|> StreamingEndpoint :<|> RawEndpoint)

type RawEndpoint =
  "raw" :> Raw

type StreamingEndpoint =
  "streaming" :> StreamBody' '[Description "netstring"] NetstringFraming JSON (SourceT IO Int) :> Stream 'GET 200 NetstringFraming JSON (SourceT IO Int)

type EmptyEndpoint =
  "empty-api" :> EmptyAPI

comprehensiveAPI :: Proxy ComprehensiveAPI
comprehensiveAPI = Proxy

type ComprehensiveAPIWithoutRaw =
  ComprehensiveAPIWithoutStreamingOrRaw'
    (EmptyEndpoint :<|> StreamingEndpoint)

comprehensiveAPIWithoutRaw :: Proxy ComprehensiveAPIWithoutRaw
comprehensiveAPIWithoutRaw = Proxy

type ComprehensiveAPIWithoutStreaming =
  ComprehensiveAPIWithoutStreamingOrRaw'
    (EmptyEndpoint :<|> RawEndpoint)

comprehensiveAPIWithoutStreaming :: Proxy ComprehensiveAPIWithoutStreaming
comprehensiveAPIWithoutStreaming = Proxy

-- | @:: API -> API@, so we have linear structure of the API.
type ComprehensiveAPIWithoutStreamingOrRaw' endpoint =
  GET
    :<|> "get-int" :> Get '[JSON] Int
    :<|> "capture" :> Capture' '[Description "example description"] "bar" Int :> GET
    :<|> "capture-lenient" :> Capture' '[Lenient] "foo" Int :> GET
    :<|> "header" :> Header "foo" Int :> GET
    :<|> "header-lenient" :> Header' '[Required, Lenient] "bar" Int :> GET
    :<|> "http-version" :> HttpVersion :> GET
    :<|> "is-secure" :> IsSecure :> GET
    :<|> "param" :> QueryParam "foo" Int :> GET
    :<|> "param-lenient" :> QueryParam' '[Required, Lenient] "bar" Int :> GET
    :<|> "params" :> QueryParams "foo" Int :> GET
    :<|> "flag" :> QueryFlag "foo" :> GET
    :<|> "remote-host" :> RemoteHost :> GET
    :<|> "req-body" :> ReqBody '[JSON] Int :> GET
    :<|> "req-body-lenient" :> ReqBody' '[Lenient] '[JSON] Int :> GET
    :<|> "res-headers" :> Get '[JSON] (Headers '[Header "foo" Int] NoContent)
    :<|> "foo" :> GET
    :<|> "vault" :> Vault :> GET
    :<|> "post-no-content" :> PostNoContent
    :<|> "post-int" :> Verb 'POST 204 '[JSON] Int
    :<|> "named-context" :> WithNamedContext "foo" '[] GET
    :<|> "capture-all" :> CaptureAll "foo" Int :> GET
    :<|> "summary" :> Summary "foo" :> GET
    :<|> "operation-id" :> OperationId "foo" :> GET
    :<|> "description" :> Description "foo" :> GET
    :<|> "alternative" :> ("left" :> GET :<|> "right" :> GET)
    :<|> "fragment" :> Fragment Int :> GET
    :<|> "resource" :> WithResource Int :> GET
    :<|> endpoint

type ComprehensiveAPIWithoutStreamingOrRaw = ComprehensiveAPIWithoutStreamingOrRaw' EmptyEndpoint

comprehensiveAPIWithoutStreamingOrRaw :: Proxy ComprehensiveAPIWithoutStreamingOrRaw
comprehensiveAPIWithoutStreamingOrRaw = Proxy
