module Ema.Route.Lib.File (
  FileRoute (..),
) where

import Ema.Route.Class (IsRoute (..))
import Ema.Route.Prism (
  toPrism_,
 )
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
import Optics.Core (coercedTo, only, (%))

{- | A type-level singleton route, whose encoding is given by the symbol parameter.

 FileRoute "foo.html" encodes to "foo.html".

 TODO: Can this type be simplified? See https://stackoverflow.com/q/72755053/55246
-}
newtype FileRoute (filename :: Symbol) = FileRoute ()
  deriving stock (FileRoute filename -> FileRoute filename -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
/= :: FileRoute filename -> FileRoute filename -> Bool
$c/= :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
== :: FileRoute filename -> FileRoute filename -> Bool
$c== :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
Eq, FileRoute filename -> FileRoute filename -> Bool
FileRoute filename -> FileRoute filename -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall (filename :: Symbol). Eq (FileRoute filename)
forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Ordering
forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> FileRoute filename
min :: FileRoute filename -> FileRoute filename -> FileRoute filename
$cmin :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> FileRoute filename
max :: FileRoute filename -> FileRoute filename -> FileRoute filename
$cmax :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> FileRoute filename
>= :: FileRoute filename -> FileRoute filename -> Bool
$c>= :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
> :: FileRoute filename -> FileRoute filename -> Bool
$c> :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
<= :: FileRoute filename -> FileRoute filename -> Bool
$c<= :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
< :: FileRoute filename -> FileRoute filename -> Bool
$c< :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Bool
compare :: FileRoute filename -> FileRoute filename -> Ordering
$ccompare :: forall (filename :: Symbol).
FileRoute filename -> FileRoute filename -> Ordering
Ord, Int -> FileRoute filename -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (filename :: Symbol). Int -> FileRoute filename -> ShowS
forall (filename :: Symbol). [FileRoute filename] -> ShowS
forall (filename :: Symbol). FileRoute filename -> String
showList :: [FileRoute filename] -> ShowS
$cshowList :: forall (filename :: Symbol). [FileRoute filename] -> ShowS
show :: FileRoute filename -> String
$cshow :: forall (filename :: Symbol). FileRoute filename -> String
showsPrec :: Int -> FileRoute filename -> ShowS
$cshowsPrec :: forall (filename :: Symbol). Int -> FileRoute filename -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (filename :: Symbol) x.
Rep (FileRoute filename) x -> FileRoute filename
forall (filename :: Symbol) x.
FileRoute filename -> Rep (FileRoute filename) x
$cto :: forall (filename :: Symbol) x.
Rep (FileRoute filename) x -> FileRoute filename
$cfrom :: forall (filename :: Symbol) x.
FileRoute filename -> Rep (FileRoute filename) x
Generic)

instance KnownSymbol fn => IsRoute (FileRoute fn) where
  type RouteModel (FileRoute fn) = ()
  routePrism :: RouteModel (FileRoute fn) -> Prism_ String (FileRoute fn)
routePrism () =
    forall s a. Prism' s a -> Prism_ s a
toPrism_ forall a b. (a -> b) -> a -> b
$
      forall a. Eq a => a -> Prism' a ()
only (forall (n :: Symbol) (proxy :: Symbol -> Type).
KnownSymbol n =>
proxy n -> String
symbolVal (forall {k} (t :: k). Proxy @k t
Proxy @fn))
        forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
       b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% forall a s. Coercible @Type s a => Iso' s a
coercedTo
  routeUniverse :: RouteModel (FileRoute fn) -> [FileRoute fn]
routeUniverse () =
    [forall (filename :: Symbol). () -> FileRoute filename
FileRoute ()]