{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}

module Http.Internal where

import qualified Control.Exception.Safe as Exception
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy
import qualified Data.Dynamic as Dynamic
import qualified Network.HTTP.Client as HTTP
import qualified Network.HTTP.Types.Header as Header
import qualified Network.Mime as Mime
import qualified Platform
import Prelude (IO)

-- | A handler for making HTTP requests.
data Handler = Handler
  { Handler
-> forall expect.
   Typeable expect =>
   Request expect -> Task Error expect
handlerRequest :: forall expect. Dynamic.Typeable expect => Request expect -> Task Error expect,
    Handler -> forall a e. (Manager -> Task e a) -> Task e a
handlerWithThirdParty :: forall a e. (HTTP.Manager -> Task e a) -> Task e a,
    Handler -> forall a. LogHandler -> (Manager -> IO a) -> IO a
handlerWithThirdPartyIO :: forall a. Platform.LogHandler -> (HTTP.Manager -> IO a) -> IO a
  }

-- | A custom request.
data Request a = Request
  { -- | The request method, like @"GET"@ or @"PUT"@.
    Request a -> Text
method :: Text,
    -- | A list of request headers.
    Request a -> [Header]
headers :: [Header],
    -- | The url, like @"https://fishes.com/salmon"@.
    Request a -> Text
url :: Text,
    -- | The request body.
    Request a -> Body
body :: Body,
    -- | The amount of microseconds you're willing to wait before giving up.
    Request a -> Maybe Int
timeout :: Maybe Int,
    -- | The type of response you expect back from the request.
    Request a -> Expect a
expect :: Expect a
  }

-- | An HTTP header for configuration requests.
newtype Header = Header {Header -> Header
unHeader :: Header.Header}
  deriving (Header -> Header -> Bool
(Header -> Header -> Bool)
-> (Header -> Header -> Bool) -> Eq Header
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Header -> Header -> Bool
$c/= :: Header -> Header -> Bool
== :: Header -> Header -> Bool
$c== :: Header -> Header -> Bool
Eq, Int -> Header -> ShowS
[Header] -> ShowS
Header -> String
(Int -> Header -> ShowS)
-> (Header -> String) -> ([Header] -> ShowS) -> Show Header
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Header] -> ShowS
$cshowList :: [Header] -> ShowS
show :: Header -> String
$cshow :: Header -> String
showsPrec :: Int -> Header -> ShowS
$cshowsPrec :: Int -> Header -> ShowS
Show)

-- | Represents the body of a Request.
data Body = Body
  { Body -> ByteString
bodyContents :: Data.ByteString.Lazy.ByteString,
    Body -> Maybe MimeType
bodyContentType :: Maybe Mime.MimeType
  }

-- |
-- Logic for interpreting a response body.
data Expect a where
  ExpectJson :: Aeson.FromJSON a => Expect a
  ExpectText :: Expect Text
  ExpectWhatever :: Expect ()

-- | A 'Request' can fail in a couple of ways:
--
-- - 'BadUrl' means you did not provide a valid URL.
-- - 'Timeout' means it took too long to get a response.
-- - 'NetworkError' means the user turned off their wifi, went in a cave, etc.
-- - 'BadStatus' means you got a response back, but the status code indicates failure.
-- - 'BadBody' means you got a response back with a nice status code, but the body of the response was something unexpected. The 'Text' in this cse is the debugging message that explains what went wrong with your JSONT decoder or whatever.
data Error
  = BadUrl Text
  | Timeout
  | NetworkError Text
  | BadStatus Int
  | BadBody Text
  deriving ((forall x. Error -> Rep Error x)
-> (forall x. Rep Error x -> Error) -> Generic Error
forall x. Rep Error x -> Error
forall x. Error -> Rep Error x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Error x -> Error
$cfrom :: forall x. Error -> Rep Error x
Generic, Error -> Error -> Bool
(Error -> Error -> Bool) -> (Error -> Error -> Bool) -> Eq Error
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Error -> Error -> Bool
$c/= :: Error -> Error -> Bool
== :: Error -> Error -> Bool
$c== :: Error -> Error -> Bool
Eq, Int -> Error -> ShowS
[Error] -> ShowS
Error -> String
(Int -> Error -> ShowS)
-> (Error -> String) -> ([Error] -> ShowS) -> Show Error
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Error] -> ShowS
$cshowList :: [Error] -> ShowS
show :: Error -> String
$cshow :: Error -> String
showsPrec :: Int -> Error -> ShowS
$cshowsPrec :: Int -> Error -> ShowS
Show)

instance Exception.Exception Error

instance Aeson.ToJSON Error