{-# LANGUAGE DeriveAnyClass #-}

{- | Route types representing the resources in our `Model`.

 See also: `Emanote.Route.SiteRoute`.
-}
module Emanote.Route.ModelRoute (
  -- Some route in a generated site
  ModelRoute (..),
  modelRouteCase,
  mkModelRouteFromFilePath,
  -- Only LML routes
  LMLRoute (..),
  defaultLmlRoute,
  possibleLmlRoutes,
  lmlRouteCase,
  withLmlRoute,
  mkLMLRouteFromFilePath,
  mkLMLRouteFromKnownFilePath,
  isMdRoute,
  -- Static file routes
  StaticFileRoute,
) where

import Data.Aeson.Types (ToJSON)
import Emanote.Route.Ext (FileType (AnyExt, LMLType), HasExt, LML (Md, Org))
import Emanote.Route.R (R)
import Emanote.Route.R qualified as R
import Relude

type StaticFileRoute = R 'AnyExt

-- | A R to anywhere in `Model`
data ModelRoute
  = ModelRoute_StaticFile StaticFileRoute
  | ModelRoute_LML LMLRoute
  deriving stock (ModelRoute -> ModelRoute -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ModelRoute -> ModelRoute -> Bool
$c/= :: ModelRoute -> ModelRoute -> Bool
== :: ModelRoute -> ModelRoute -> Bool
$c== :: ModelRoute -> ModelRoute -> Bool
Eq, Int -> ModelRoute -> ShowS
[ModelRoute] -> ShowS
ModelRoute -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ModelRoute] -> ShowS
$cshowList :: [ModelRoute] -> ShowS
show :: ModelRoute -> String
$cshow :: ModelRoute -> String
showsPrec :: Int -> ModelRoute -> ShowS
$cshowsPrec :: Int -> ModelRoute -> ShowS
Show, Eq ModelRoute
ModelRoute -> ModelRoute -> Bool
ModelRoute -> ModelRoute -> Ordering
ModelRoute -> ModelRoute -> ModelRoute
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
min :: ModelRoute -> ModelRoute -> ModelRoute
$cmin :: ModelRoute -> ModelRoute -> ModelRoute
max :: ModelRoute -> ModelRoute -> ModelRoute
$cmax :: ModelRoute -> ModelRoute -> ModelRoute
>= :: ModelRoute -> ModelRoute -> Bool
$c>= :: ModelRoute -> ModelRoute -> Bool
> :: ModelRoute -> ModelRoute -> Bool
$c> :: ModelRoute -> ModelRoute -> Bool
<= :: ModelRoute -> ModelRoute -> Bool
$c<= :: ModelRoute -> ModelRoute -> Bool
< :: ModelRoute -> ModelRoute -> Bool
$c< :: ModelRoute -> ModelRoute -> Bool
compare :: ModelRoute -> ModelRoute -> Ordering
$ccompare :: ModelRoute -> ModelRoute -> Ordering
Ord, forall x. Rep ModelRoute x -> ModelRoute
forall x. ModelRoute -> Rep ModelRoute x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ModelRoute x -> ModelRoute
$cfrom :: forall x. ModelRoute -> Rep ModelRoute x
Generic)
  deriving anyclass ([ModelRoute] -> Encoding
[ModelRoute] -> Value
ModelRoute -> Encoding
ModelRoute -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [ModelRoute] -> Encoding
$ctoEncodingList :: [ModelRoute] -> Encoding
toJSONList :: [ModelRoute] -> Value
$ctoJSONList :: [ModelRoute] -> Value
toEncoding :: ModelRoute -> Encoding
$ctoEncoding :: ModelRoute -> Encoding
toJSON :: ModelRoute -> Value
$ctoJSON :: ModelRoute -> Value
ToJSON)

-- | R to a note file in LML (lightweight markup language) format
data LMLRoute
  = LMLRoute_Md (R ('LMLType 'Md))
  | LMLRoute_Org (R ('LMLType 'Org))
  deriving stock (LMLRoute -> LMLRoute -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: LMLRoute -> LMLRoute -> Bool
$c/= :: LMLRoute -> LMLRoute -> Bool
== :: LMLRoute -> LMLRoute -> Bool
$c== :: LMLRoute -> LMLRoute -> Bool
Eq, Int -> LMLRoute -> ShowS
[LMLRoute] -> ShowS
LMLRoute -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [LMLRoute] -> ShowS
$cshowList :: [LMLRoute] -> ShowS
show :: LMLRoute -> String
$cshow :: LMLRoute -> String
showsPrec :: Int -> LMLRoute -> ShowS
$cshowsPrec :: Int -> LMLRoute -> ShowS
Show, Eq LMLRoute
LMLRoute -> LMLRoute -> Bool
LMLRoute -> LMLRoute -> Ordering
LMLRoute -> LMLRoute -> LMLRoute
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
min :: LMLRoute -> LMLRoute -> LMLRoute
$cmin :: LMLRoute -> LMLRoute -> LMLRoute
max :: LMLRoute -> LMLRoute -> LMLRoute
$cmax :: LMLRoute -> LMLRoute -> LMLRoute
>= :: LMLRoute -> LMLRoute -> Bool
$c>= :: LMLRoute -> LMLRoute -> Bool
> :: LMLRoute -> LMLRoute -> Bool
$c> :: LMLRoute -> LMLRoute -> Bool
<= :: LMLRoute -> LMLRoute -> Bool
$c<= :: LMLRoute -> LMLRoute -> Bool
< :: LMLRoute -> LMLRoute -> Bool
$c< :: LMLRoute -> LMLRoute -> Bool
compare :: LMLRoute -> LMLRoute -> Ordering
$ccompare :: LMLRoute -> LMLRoute -> Ordering
Ord, forall x. Rep LMLRoute x -> LMLRoute
forall x. LMLRoute -> Rep LMLRoute x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep LMLRoute x -> LMLRoute
$cfrom :: forall x. LMLRoute -> Rep LMLRoute x
Generic)
  deriving anyclass ([LMLRoute] -> Encoding
[LMLRoute] -> Value
LMLRoute -> Encoding
LMLRoute -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [LMLRoute] -> Encoding
$ctoEncodingList :: [LMLRoute] -> Encoding
toJSONList :: [LMLRoute] -> Value
$ctoJSONList :: [LMLRoute] -> Value
toEncoding :: LMLRoute -> Encoding
$ctoEncoding :: LMLRoute -> Encoding
toJSON :: LMLRoute -> Value
$ctoJSON :: LMLRoute -> Value
ToJSON)

defaultLmlRoute :: R (ext :: FileType a) -> LMLRoute
defaultLmlRoute :: forall a (ext :: FileType a). R @a ext -> LMLRoute
defaultLmlRoute =
  R @SourceExt ('LMLType 'Md) -> LMLRoute
LMLRoute_Md forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible @Type a b => a -> b
coerce

possibleLmlRoutes :: R (ext :: FileType a) -> [LMLRoute]
possibleLmlRoutes :: forall a (ext :: FileType a). R @a ext -> [LMLRoute]
possibleLmlRoutes R @a ext
r =
  [ R @SourceExt ('LMLType 'Md) -> LMLRoute
LMLRoute_Md (coerce :: forall a b. Coercible @Type a b => a -> b
coerce R @a ext
r)
  , R @SourceExt ('LMLType 'Org) -> LMLRoute
LMLRoute_Org (coerce :: forall a b. Coercible @Type a b => a -> b
coerce R @a ext
r)
  ]

lmlRouteCase ::
  LMLRoute ->
  Either (R ('LMLType 'Md)) (R ('LMLType 'Org))
lmlRouteCase :: LMLRoute
-> Either
     (R @SourceExt ('LMLType 'Md)) (R @SourceExt ('LMLType 'Org))
lmlRouteCase = \case
  LMLRoute_Md R @SourceExt ('LMLType 'Md)
r -> forall a b. a -> Either a b
Left R @SourceExt ('LMLType 'Md)
r
  LMLRoute_Org R @SourceExt ('LMLType 'Org)
r -> forall a b. b -> Either a b
Right R @SourceExt ('LMLType 'Org)
r

isMdRoute :: LMLRoute -> Bool
isMdRoute :: LMLRoute -> Bool
isMdRoute = \case
  LMLRoute_Md R @SourceExt ('LMLType 'Md)
_ -> Bool
True
  LMLRoute
_ -> Bool
False

withLmlRoute :: (forall lmlType. HasExt ('LMLType lmlType) => R ('LMLType lmlType) -> r) -> LMLRoute -> r
withLmlRoute :: forall r.
(forall (lmlType :: LML).
 HasExt @SourceExt ('LMLType lmlType) =>
 R @SourceExt ('LMLType lmlType) -> r)
-> LMLRoute -> r
withLmlRoute forall (lmlType :: LML).
HasExt @SourceExt ('LMLType lmlType) =>
R @SourceExt ('LMLType lmlType) -> r
f = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (lmlType :: LML).
HasExt @SourceExt ('LMLType lmlType) =>
R @SourceExt ('LMLType lmlType) -> r
f forall (lmlType :: LML).
HasExt @SourceExt ('LMLType lmlType) =>
R @SourceExt ('LMLType lmlType) -> r
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. LMLRoute
-> Either
     (R @SourceExt ('LMLType 'Md)) (R @SourceExt ('LMLType 'Org))
lmlRouteCase

modelRouteCase ::
  ModelRoute ->
  Either LMLRoute StaticFileRoute
modelRouteCase :: ModelRoute -> Either LMLRoute StaticFileRoute
modelRouteCase = \case
  ModelRoute_LML LMLRoute
r -> forall a b. a -> Either a b
Left LMLRoute
r
  ModelRoute_StaticFile StaticFileRoute
r -> forall a b. b -> Either a b
Right StaticFileRoute
r

mkModelRouteFromFilePath :: FilePath -> Maybe ModelRoute
mkModelRouteFromFilePath :: String -> Maybe ModelRoute
mkModelRouteFromFilePath String
fp =
  forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap LMLRoute -> ModelRoute
ModelRoute_LML (String -> Maybe LMLRoute
mkLMLRouteFromFilePath String
fp)
    forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap StaticFileRoute -> ModelRoute
ModelRoute_StaticFile (forall a (ext :: FileType a).
HasExt @a ext =>
String -> Maybe (R @a ext)
R.mkRouteFromFilePath String
fp)

mkLMLRouteFromFilePath :: FilePath -> Maybe LMLRoute
mkLMLRouteFromFilePath :: String -> Maybe LMLRoute
mkLMLRouteFromFilePath String
fp =
  LML -> String -> Maybe LMLRoute
mkLMLRouteFromKnownFilePath LML
Md String
fp
    forall (f :: Type -> Type) a. Alternative f => f a -> f a -> f a
<|> LML -> String -> Maybe LMLRoute
mkLMLRouteFromKnownFilePath LML
Org String
fp

{- | Like `mkLMLRouteFromFilePath`, but when the file extension is known ahead
 to be of `lmlType`.
-}
mkLMLRouteFromKnownFilePath :: LML -> FilePath -> Maybe LMLRoute
mkLMLRouteFromKnownFilePath :: LML -> String -> Maybe LMLRoute
mkLMLRouteFromKnownFilePath LML
lmlType String
fp =
  case LML
lmlType of
    LML
Md -> forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap R @SourceExt ('LMLType 'Md) -> LMLRoute
LMLRoute_Md (forall a (ext :: FileType a).
HasExt @a ext =>
String -> Maybe (R @a ext)
R.mkRouteFromFilePath String
fp)
    LML
Org -> forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap R @SourceExt ('LMLType 'Org) -> LMLRoute
LMLRoute_Org (forall a (ext :: FileType a).
HasExt @a ext =>
String -> Maybe (R @a ext)
R.mkRouteFromFilePath String
fp)