module Data.Aviation.Stratux.HTTP(
  stratuxHTTP
, getWith
, getStatusWith
, getStatus
, getStatus'
, getSettingsWith
, getSettings
, getSettings'
) where

import Control.Applicative((<$>))
import Control.Monad((>>=))
import Control.Monad.Trans.Either(EitherT(EitherT))
import Data.Aeson(eitherDecode, eitherDecode')
import Data.Aviation.Stratux.Types.Status(Status)
import Data.Aviation.Stratux.Types.Settings(Settings)
import Data.Either(Either)
import Data.Maybe(Maybe(Just))
import Data.String(String)
import Network.HTTP(RequestMethod(GET), simpleHTTP, mkRequest, getResponseBody)
import Network.TCP(HStream)
import Network.URI(URI(URI), URIAuth)
import System.IO(IO)

stratuxHTTP :: 
  HStream b =>
  URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ @\/ghc@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@    
  -> IO b
stratuxHTTP auth path query fragment =
  simpleHTTP (mkRequest GET (URI "http:" (Just auth) path query fragment)) >>= getResponseBody

getWith :: 
  HStream x =>
  String -- ^ @\/ghc@
  -> (x -> Either e a)
  -> URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT e IO a
getWith path d auth query fragment =
  EitherT (d <$> stratuxHTTP auth path query fragment)

getStatusWith :: 
  HStream x =>
  (x -> Either e Status)
  -> URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT e IO Status
getStatusWith =
  getWith "/getStatus"

getStatus ::
  URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT String IO Status
getStatus =
  getStatusWith eitherDecode

getStatus' ::
  URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT String IO Status
getStatus' =
  getStatusWith eitherDecode'

getSettingsWith :: 
  HStream x =>
  (x -> Either e Settings)
  -> URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT e IO Settings
getSettingsWith =
  getWith "/getSettings"

getSettings ::
  URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT String IO Settings
getSettings =
  getSettingsWith eitherDecode

getSettings' ::
  URIAuth -- ^ authority @\/\/anonymous\@www.haskell.org:42@
  -> String -- ^ query @?query@
  -> String -- ^ fragment @#frag@
  -> EitherT String IO Settings
getSettings' =
  getSettingsWith eitherDecode'