content: {-# OPTIONS_HADDOCK not-home #-}
  
  {- |
  Module      : Servant.API.Routes.Internal.Path
  Copyright   : (c) Frederick Pringle, 2025
  License     : BSD-3-Clause
  Maintainer  : frederick.pringle@fpringle.com
  
  Internal module, subject to change.
  -}
  module Servant.API.Routes.Internal.Path
    ( Path (..)
    , renderPath
    , pathSeparator
    , PathPart (..)
    )
  where
  
  import Data.Aeson
  import Data.String
  import qualified Data.Text as T
  import Data.Typeable
  
  -- | A segment of an API path (between @"/"@s).
  data PathPart
    = -- | Just a plain path part, e.g. @"api/"@.
      StringPart T.Text
    | -- | Capture a path part as a variable.
      CapturePart T.Text TypeRep
    | -- | Capture all path part as a list of variables.
      CaptureAllPart T.Text TypeRep
    deriving (Eq, Ord)
  
  instance IsString PathPart where
    fromString = StringPart . T.pack
  
  instance Show PathPart where
    show = T.unpack . renderPathPart
  
  -- | Pretty-print a path part.
  renderPathPart :: PathPart -> T.Text
  renderPathPart = \case
    StringPart t -> t
    CapturePart _ typ -> "<" <> T.pack (show typ) <> ">"
    CaptureAllPart _ typ -> "<[" <> T.pack (show typ) <> "]>"
  
  -- | Standard path separator @"/"@.
  pathSeparator :: T.Text
  pathSeparator = "/"
  
  -- | Simple representation of a URL path.
  newtype Path = Path
    { unPath :: [PathPart]
    }
    deriving (Eq, Ord) via [PathPart]
  
  instance Show Path where
    show = T.unpack . renderPath
  
  instance ToJSON Path where
    toJSON = toJSON . renderPath
  
  -- | Pretty-print a path, including the leading @/@.
  renderPath :: Path -> T.Text
  renderPath = (pathSeparator <>) . T.intercalate pathSeparator . fmap renderPathPart . unPath
  