{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables   #-}
{-# LANGUAGE TypeFamilies          #-}

module Servant.Elm.Internal.Foreign where

import           Data.Proxy      (Proxy (Proxy))
import           Data.Typeable   (Typeable)
import           Elm.TyRep       (EType, toElmType)
import           Servant.API     (Headers(..))
import           Servant.Foreign (Foreign, GenerateList, HasForeign,
                                  HasForeignType, Req, listFromAPI, typeFor)


data LangElm

--- TODO: Generate Elm functions that can handle the response headers. PRs
--- welcome!
instance {-# OVERLAPPING #-} (Typeable a) => HasForeignType LangElm EType (Headers b a) where
  typeFor :: Proxy LangElm -> Proxy EType -> Proxy (Headers b a) -> EType
typeFor Proxy LangElm
_ Proxy EType
_ Proxy (Headers b a)
_ = forall a. Typeable a => Proxy a -> EType
toElmType (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)

instance {-# OVERLAPPABLE #-} (Typeable a) => HasForeignType LangElm EType a where
  typeFor :: Proxy LangElm -> Proxy EType -> Proxy a -> EType
typeFor Proxy LangElm
_ Proxy EType
_ Proxy a
_ = forall a. Typeable a => Proxy a -> EType
toElmType (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)

getEndpoints
  :: ( HasForeign LangElm EType api
     , GenerateList EType (Foreign EType api))
  => Proxy api
  -> [Req EType]
getEndpoints :: forall api.
(HasForeign LangElm EType api,
 GenerateList EType (Foreign EType api)) =>
Proxy api -> [Req EType]
getEndpoints =
  forall {k} (lang :: k) ftype api.
(HasForeign lang ftype api,
 GenerateList ftype (Foreign ftype api)) =>
Proxy lang -> Proxy ftype -> Proxy api -> [Req ftype]
listFromAPI (forall {k} (t :: k). Proxy t
Proxy :: Proxy LangElm) (forall {k} (t :: k). Proxy t
Proxy :: Proxy EType)