module System.Process.Quick.Predicate.InDir where

import Data.Typeable (eqT)
import System.Directory
import System.Process.Quick.Predicate
import System.Process.Quick.Predicate.InFile ( genFilePathBy )
import System.Process.Quick.Prelude
import Text.Regex.TDFA ((=~))
import Type.Reflection ((:~:)(Refl))

data InDir deriving (Typeable InDir
Typeable InDir =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> InDir -> c InDir)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c InDir)
-> (InDir -> Constr)
-> (InDir -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c InDir))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c InDir))
-> ((forall b. Data b => b -> b) -> InDir -> InDir)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r)
-> (forall u. (forall d. Data d => d -> u) -> InDir -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> InDir -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> InDir -> m InDir)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> InDir -> m InDir)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> InDir -> m InDir)
-> Data InDir
InDir -> Constr
InDir -> DataType
(forall b. Data b => b -> b) -> InDir -> InDir
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> InDir -> u
forall u. (forall d. Data d => d -> u) -> InDir -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c InDir
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> InDir -> c InDir
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c InDir)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c InDir)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> InDir -> c InDir
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> InDir -> c InDir
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c InDir
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c InDir
$ctoConstr :: InDir -> Constr
toConstr :: InDir -> Constr
$cdataTypeOf :: InDir -> DataType
dataTypeOf :: InDir -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c InDir)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c InDir)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c InDir)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c InDir)
$cgmapT :: (forall b. Data b => b -> b) -> InDir -> InDir
gmapT :: (forall b. Data b => b -> b) -> InDir -> InDir
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> InDir -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> InDir -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> InDir -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> InDir -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> InDir -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> InDir -> m InDir
Data, Int -> InDir -> ShowS
[InDir] -> ShowS
InDir -> String
(Int -> InDir -> ShowS)
-> (InDir -> String) -> ([InDir] -> ShowS) -> Show InDir
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> InDir -> ShowS
showsPrec :: Int -> InDir -> ShowS
$cshow :: InDir -> String
show :: InDir -> String
$cshowList :: [InDir] -> ShowS
showList :: [InDir] -> ShowS
Show, InDir -> InDir -> Bool
(InDir -> InDir -> Bool) -> (InDir -> InDir -> Bool) -> Eq InDir
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InDir -> InDir -> Bool
== :: InDir -> InDir -> Bool
$c/= :: InDir -> InDir -> Bool
/= :: InDir -> InDir -> Bool
Eq, (forall x. InDir -> Rep InDir x)
-> (forall x. Rep InDir x -> InDir) -> Generic InDir
forall x. Rep InDir x -> InDir
forall x. InDir -> Rep InDir x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. InDir -> Rep InDir x
from :: forall x. InDir -> Rep InDir x
$cto :: forall x. Rep InDir x -> InDir
to :: forall x. Rep InDir x -> InDir
Generic)

instance Predicate InDir FilePath where
  validate :: Proxy InDir -> String -> Maybe RefineException
validate Proxy InDir
p String
x
    | String
x String -> String -> Bool
forall source source1 target.
(RegexMaker Regex CompOption ExecOption source,
 RegexContext Regex source1 target) =>
source1 -> source -> target
=~ (String
"^([.~]?[/])?[^/\x0000-\x001F]+([/][^/\x0000-\x001F]+)*[/]?$" :: String)
    = Maybe RefineException
forall a. Maybe a
Nothing
    | Bool
otherwise
    = TypeRep -> Text -> Maybe RefineException
throwRefineOtherException (Proxy InDir -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep Proxy InDir
p) (Text -> Maybe RefineException) -> Text -> Maybe RefineException
forall a b. (a -> b) -> a -> b
$ Text
"Bad FilePath " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a. ToText a => a -> Text
toText String
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"]"

instance {-# OVERLAPPING #-} Arbitrary (Refined InDir FilePath) where
  arbitrary :: Gen (Refined InDir String)
arbitrary =
    Proxy "*" -> Gen String
forall (e :: Symbol). KnownSymbol e => Proxy e -> Gen String
genFilePathBy (forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @"*") Gen String
-> (String -> Gen (Refined InDir String))
-> Gen (Refined InDir String)
forall a b. Gen a -> (a -> Gen b) -> Gen b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Refined InDir String -> Gen (Refined InDir String)
forall a. a -> Gen a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Refined InDir String -> Gen (Refined InDir String))
-> (String -> Refined InDir String)
-> String
-> Gen (Refined InDir String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Refined InDir String
forall {k} (p :: k) a. (Predicate p a, Show a) => a -> Refined p a
refinErr

findRefinedDirs :: forall m x. (MonadIO m, Data x) => x -> m x
findRefinedDirs :: forall (m :: * -> *) x. (MonadIO m, Data x) => x -> m x
findRefinedDirs x
x
  | Just x :~: Refined InDir String
Refl <- forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
eqT @x @(Refined InDir FilePath) =
      let fp :: String
fp = Refined InDir String -> String
forall {k} (p :: k) x. Refined p x -> x
unrefine x
Refined InDir String
x in do
        IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Bool -> String -> IO ()
createDirectoryIfMissing Bool
True String
fp)
        x -> m x
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure x
x
  | Bool
otherwise =
      x -> m x
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure x
x

instance RefinedInArgLocator (Refined InDir FilePath) where
  locateRefinedInArg :: forall (m :: * -> *).
Proxy (Refined InDir String) -> ArgCollector m
locateRefinedInArg Proxy (Refined InDir String)
_ = v -> m v
forall (m :: * -> *) x. (MonadIO m, Data x) => x -> m x
findRefinedDirs