module Hinit.Optionals where

import Control.Effect.Throw
import Data.Algebra.Boolean
import qualified Data.List.NonEmpty as NE
import qualified Data.Map.Strict as M
import Data.Maybe
import Data.Text (Text)
import Hinit.Errors
import Hinit.Template.Config
import Hinit.Types
import System.FilePath.Glob
import Text.Megaparsec

defaultIgnores :: [Pattern]
defaultIgnores :: [Pattern]
defaultIgnores =
  [ Pattern
"template.toml",
    Pattern
".git",
    Pattern
".pijul",
    Pattern
".hg",
    Pattern
"_darcs",
    Pattern
".gitkeep",
    Pattern
"**/.gitkeep"
  ]

parseExpr :: Has (Throw ExprParseError) sig m => Text -> m Expr
parseExpr :: Text -> m Expr
parseExpr Text
expr' =
  case Parsec Void Text Expr
-> String -> Text -> Either (ParseErrorBundle Text Void) Expr
forall e s a.
Parsec e s a -> String -> s -> Either (ParseErrorBundle s e) a
runParser Parsec Void Text Expr
expr String
"" Text
expr' of
    Left ParseErrorBundle {NonEmpty (ParseError Text Void)
PosState Text
bundleErrors :: forall s e. ParseErrorBundle s e -> NonEmpty (ParseError s e)
bundlePosState :: forall s e. ParseErrorBundle s e -> PosState s
bundlePosState :: PosState Text
bundleErrors :: NonEmpty (ParseError Text Void)
..} ->
      ExprParseError -> m Expr
forall e (sig :: (Type -> Type) -> Type -> Type)
       (m :: Type -> Type) a.
Has (Throw e) sig m =>
e -> m a
throwError (ExprParseError -> m Expr) -> ExprParseError -> m Expr
forall a b. (a -> b) -> a -> b
$ Text -> [ParseError Text Void] -> ExprParseError
ExprParseError Text
expr' ([ParseError Text Void] -> ExprParseError)
-> [ParseError Text Void] -> ExprParseError
forall a b. (a -> b) -> a -> b
$ NonEmpty (ParseError Text Void) -> [ParseError Text Void]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty (ParseError Text Void)
bundleErrors
    Right Expr
e -> Expr -> m Expr
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Expr
e

booleanContext :: Context -> CTX
booleanContext :: Context -> CTX
booleanContext Context
ctx = [(Text, Bool)] -> CTX
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(Text, Bool)] -> CTX) -> [(Text, Bool)] -> CTX
forall a b. (a -> b) -> a -> b
$ ((Text, Val) -> Maybe (Text, Bool))
-> [(Text, Val)] -> [(Text, Bool)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Text, Val) -> Maybe (Text, Bool)
forall a. (a, Val) -> Maybe (a, Bool)
m ([(Text, Val)] -> [(Text, Bool)])
-> [(Text, Val)] -> [(Text, Bool)]
forall a b. (a -> b) -> a -> b
$ Context -> [(Text, Val)]
forall k a. Map k a -> [(k, a)]
M.toList Context
ctx
  where
    m :: (a, Val) -> Maybe (a, Bool)
m (a
t, Bool Bool
b) = (a, Bool) -> Maybe (a, Bool)
forall a. a -> Maybe a
Just (a
t, Bool
b)
    m (a, Val)
_ = Maybe (a, Bool)
forall a. Maybe a
Nothing

ignoredFiles ::
  Has (Throw ExprParseError) sig m =>
  Context ->
  TemplateConfig ->
  m [Pattern]
ignoredFiles :: Context -> TemplateConfig -> m [Pattern]
ignoredFiles Context
ctx TemplateConfig {[Pattern]
[Text]
[OptionalIgnores]
[Option]
Maybe Text
$sel:optionals:TemplateConfig :: TemplateConfig -> [OptionalIgnores]
$sel:options:TemplateConfig :: TemplateConfig -> [Option]
$sel:ignores:TemplateConfig :: TemplateConfig -> [Pattern]
$sel:tags:TemplateConfig :: TemplateConfig -> [Text]
$sel:desc:TemplateConfig :: TemplateConfig -> Maybe Text
optionals :: [OptionalIgnores]
options :: [Option]
ignores :: [Pattern]
tags :: [Text]
desc :: Maybe Text
..} = do
  [[Pattern]]
l <- (OptionalIgnores -> m [Pattern])
-> [OptionalIgnores] -> m [[Pattern]]
forall (t :: Type -> Type) (f :: Type -> Type) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse OptionalIgnores -> m [Pattern]
ignoredFiles' [OptionalIgnores]
optionals
  [Pattern] -> m [Pattern]
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ([Pattern] -> m [Pattern]) -> [Pattern] -> m [Pattern]
forall a b. (a -> b) -> a -> b
$ [Pattern]
defaultIgnores [Pattern] -> [Pattern] -> [Pattern]
forall a. Semigroup a => a -> a -> a
<> [Pattern]
ignores [Pattern] -> [Pattern] -> [Pattern]
forall a. Semigroup a => a -> a -> a
<> [[Pattern]] -> [Pattern]
forall (t :: Type -> Type) a. Foldable t => t [a] -> [a]
concat [[Pattern]]
l
  where
    ctx' :: CTX
ctx' = Context -> CTX
booleanContext Context
ctx
    ignoredFiles' :: OptionalIgnores -> m [Pattern]
ignoredFiles' Optional {[Pattern]
Text
$sel:ignores:Optional :: OptionalIgnores -> [Pattern]
$sel:when:Optional :: OptionalIgnores -> Text
ignores :: [Pattern]
when :: Text
..} = do
      Expr
expr' <- Text -> m Expr
forall (sig :: (Type -> Type) -> Type -> Type) (m :: Type -> Type).
Has (Throw ExprParseError) sig m =>
Text -> m Expr
parseExpr Text
when
      if CTX -> Expr -> Bool
eval CTX
ctx' Expr
expr'
        then [Pattern] -> m [Pattern]
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure [Pattern]
ignores
        else [Pattern] -> m [Pattern]
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure []