{-# LANGUAGE
    Arrows
  , GeneralizedNewtypeDeriving
  , OverloadedStrings
  , TypeOperators
  , UnicodeSyntax
  #-}
-- |FIXME: doc
module Network.HTTP.Lucu.Router
    ( -- * The 'Router' arrow
      Router
    , runRouter

      -- * Testing for URI scheme
    , anyScheme
    , scheme
    , http
    , http'
    , https
    )
    where
import Control.Applicative
import Control.Category
import Control.Arrow
import Control.Arrow.ArrowKleisli
import Control.Arrow.List
import Control.Monad.IO.Class
import Data.Ascii (CIAscii)
import Data.Maybe
import Network.URI hiding (scheme)
import Network.HTTP.Lucu.Utils
import Prelude.Unicode

-- |FIXME: doc
newtype Router m α β
    = Router {
        unRouter ∷ ListTArrow m α β
      }
    deriving ( Arrow
             , ArrowKleisli m
             , ArrowZero
             , ArrowPlus
             , ArrowChoice
             , ArrowApply
             , Category
             )

-- |FIXME: doc
runRouter ∷ (Applicative m, MonadIO m) ⇒ Router m α β → α → m (Maybe β)
{-# INLINE runRouter #-}
runRouter = ((listToMaybe <$>) ∘) ∘ runListTArrow ∘ unRouter

-- |FIXME: doc
anyScheme ∷ Arrow (⇝) ⇒ URI ⇝ (Host, Path)
{-# INLINEABLE anyScheme #-}
anyScheme = arr uriHost &&& arr uriPathSegments

-- |FIXME: doc
scheme ∷ (ArrowChoice (⇝), ArrowZero (⇝)) ⇒ CIAscii → URI ⇝ (Host, Path)
{-# INLINEABLE scheme #-}
scheme s
    = proc uri →
      if s ≡ uriCIScheme uri then
          anyScheme ⤙ uri
      else
          zeroArrow ⤙ (⊥)

-- |@'http' = 'scheme' \"http\" '<+>' 'scheme' \"https\"@
http ∷ (ArrowChoice (⇝), ArrowPlus (⇝), ArrowZero (⇝)) ⇒ URI ⇝ (Host, Path)
{-# INLINE http #-}
http = scheme "http" <+> scheme "https"

-- |@'http'' = 'scheme' \"http\"@
http' ∷ (ArrowChoice (⇝), ArrowZero (⇝)) ⇒ URI ⇝ (Host, Path)
http' = scheme "http"

-- |@'https' = 'scheme' \"https\"@
https ∷ (ArrowChoice (⇝), ArrowZero (⇝)) ⇒ URI ⇝ (Host, Path)
https = scheme "https"