{-# LANGUAGE
    KindSignatures
  , GADTs
  , RankNTypes
  , TypeOperators
  , DataKinds
  #-}

module Web.Routes.Nested.Types.UrlChunks where

import Data.Attoparsec.Text
import Text.Regex
import Data.String (IsString (..))
import qualified Data.Text as T


-- | Constrained to AttoParsec & T.Text
data EitherUrlChunk (x :: Maybe *) where
  (:=) :: T.Text             -> EitherUrlChunk 'Nothing
  (:~) :: (T.Text, Parser r) -> EitherUrlChunk ('Just r)
  (:*) :: (T.Text, Regex)    -> EitherUrlChunk ('Just [String])

l :: T.Text -> EitherUrlChunk 'Nothing
l = (:=)

instance x ~ 'Nothing => IsString (EitherUrlChunk x) where
  fromString = l . T.pack

p :: (T.Text, Parser r) -> EitherUrlChunk ('Just r)
p = (:~)

r :: (T.Text, Regex) -> EitherUrlChunk ('Just [String])
r = (:*)

-- | Container when defining route paths
data UrlChunks (xs :: [Maybe *]) where
  Cons :: EitherUrlChunk mx -> UrlChunks xs -> UrlChunks (mx ': xs) -- stack is left-to-right
  Root  :: UrlChunks '[]

(</>) :: EitherUrlChunk mx -> UrlChunks xs -> UrlChunks (mx ': xs)
(</>) = Cons

infixr 9 </>

o :: UrlChunks '[]
o = Root