{-# LANGUAGE DeriveGeneric, DuplicateRecordFields, DeriveDataTypeable, OverloadedStrings #-}

module Rob.Types where

import GHC.Generics (Generic(..))
import Data.HashMap.Strict (HashMap)
import System.FilePath.Glob (Pattern)
import Data.Text (Text)
import Data.Yaml
import System.Console.CmdArgs

-- | Task struct listing all the available actions
data Task
  = Add {
    Task -> String
name :: String,
    Task -> String
path :: FilePath
  }
  | List
  | Remove
  | New deriving (Typeable Task
DataType
Constr
Typeable Task
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Task -> c Task)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Task)
-> (Task -> Constr)
-> (Task -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Task))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Task))
-> ((forall b. Data b => b -> b) -> Task -> Task)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r)
-> (forall u. (forall d. Data d => d -> u) -> Task -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Task -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Task -> m Task)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Task -> m Task)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Task -> m Task)
-> Data Task
Task -> DataType
Task -> Constr
(forall b. Data b => b -> b) -> Task -> Task
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Task -> c Task
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Task
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) -> Task -> u
forall u. (forall d. Data d => d -> u) -> Task -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Task -> m Task
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Task -> m Task
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Task
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Task -> c Task
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Task)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Task)
$cNew :: Constr
$cRemove :: Constr
$cList :: Constr
$cAdd :: Constr
$tTask :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Task -> m Task
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Task -> m Task
gmapMp :: (forall d. Data d => d -> m d) -> Task -> m Task
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Task -> m Task
gmapM :: (forall d. Data d => d -> m d) -> Task -> m Task
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Task -> m Task
gmapQi :: Int -> (forall d. Data d => d -> u) -> Task -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Task -> u
gmapQ :: (forall d. Data d => d -> u) -> Task -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Task -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Task -> r
gmapT :: (forall b. Data b => b -> b) -> Task -> Task
$cgmapT :: (forall b. Data b => b -> b) -> Task -> Task
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Task)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Task)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Task)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Task)
dataTypeOf :: Task -> DataType
$cdataTypeOf :: Task -> DataType
toConstr :: Task -> Constr
$ctoConstr :: Task -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Task
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Task
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Task -> c Task
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Task -> c Task
$cp1Data :: Typeable Task
Data, Typeable, Int -> Task -> ShowS
[Task] -> ShowS
Task -> String
(Int -> Task -> ShowS)
-> (Task -> String) -> ([Task] -> ShowS) -> Show Task
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Task] -> ShowS
$cshowList :: [Task] -> ShowS
show :: Task -> String
$cshow :: Task -> String
showsPrec :: Int -> Task -> ShowS
$cshowsPrec :: Int -> Task -> ShowS
Show)

-- | Template name + path
data Template = Template String FilePath deriving ((forall x. Template -> Rep Template x)
-> (forall x. Rep Template x -> Template) -> Generic Template
forall x. Rep Template x -> Template
forall x. Template -> Rep Template x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Template x -> Template
$cfrom :: forall x. Template -> Rep Template x
Generic)

instance Show Template where
  show :: Template -> String
show (Template String
name String
path) = [String] -> String
unlines [
      String
"- Name: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
name,
      String
"  Path: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
path
    ]

instance Eq Template where
  (Template String
nameA String
_) == :: Template -> Template -> Bool
== (Template String
nameB String
_) = String
nameA String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
nameB

instance FromJSON Template
instance ToJSON Template

-- | Config file struct
newtype Config = Config {
  Config -> [Template]
templates :: [Template]
} deriving ((forall x. Config -> Rep Config x)
-> (forall x. Rep Config x -> Config) -> Generic Config
forall x. Rep Config x -> Config
forall x. Config -> Rep Config x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Config x -> Config
$cfrom :: forall x. Config -> Rep Config x
Generic, Int -> Config -> ShowS
[Config] -> ShowS
Config -> String
(Int -> Config -> ShowS)
-> (Config -> String) -> ([Config] -> ShowS) -> Show Config
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Config] -> ShowS
$cshowList :: [Config] -> ShowS
show :: Config -> String
$cshow :: Config -> String
showsPrec :: Int -> Config -> ShowS
$cshowsPrec :: Int -> Config -> ShowS
Show, Config -> Config -> Bool
(Config -> Config -> Bool)
-> (Config -> Config -> Bool) -> Eq Config
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Config -> Config -> Bool
$c/= :: Config -> Config -> Bool
== :: Config -> Config -> Bool
$c== :: Config -> Config -> Bool
Eq)

instance FromJSON Config
instance ToJSON Config

-- | Question struct
data Question =
    SimpleQuestion String String
  | PasswordQuestion String
  | ConfirmQuestion String Bool
  | SelectQuestion String [String] String
  | MultiselectQuestion String [String] [String]
  deriving (Int -> Question -> ShowS
[Question] -> ShowS
Question -> String
(Int -> Question -> ShowS)
-> (Question -> String) -> ([Question] -> ShowS) -> Show Question
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Question] -> ShowS
$cshowList :: [Question] -> ShowS
show :: Question -> String
$cshow :: Question -> String
showsPrec :: Int -> Question -> ShowS
$cshowsPrec :: Int -> Question -> ShowS
Show, Question -> Question -> Bool
(Question -> Question -> Bool)
-> (Question -> Question -> Bool) -> Eq Question
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Question -> Question -> Bool
$c/= :: Question -> Question -> Bool
== :: Question -> Question -> Bool
$c== :: Question -> Question -> Bool
Eq)

instance FromJSON Question where
  parseJSON :: Value -> Parser Question
parseJSON (Object Object
v) = do
    String
questionType <- Object
v Object -> Text -> Parser (Maybe String)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"type" Parser (Maybe String) -> String -> Parser String
forall a. Parser (Maybe a) -> a -> Parser a
.!= String
"simple"
    Value -> Parser Value
forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
v) Parser Value -> (Value -> Parser Question) -> Parser Question
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> Value -> Parser Question
parseQuestion String
questionType

parseQuestion :: String -> Value -> Parser Question
parseQuestion :: String -> Value -> Parser Question
parseQuestion String
questionType =
  case String
questionType of
    String
"confirm" -> String -> (Object -> Parser Question) -> Value -> Parser Question
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"ConfirmQuestion"
      (\Object
o -> String -> Bool -> Question
ConfirmQuestion (String -> Bool -> Question)
-> Parser String -> Parser (Bool -> Question)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
questionKey Parser (Bool -> Question) -> Parser Bool -> Parser Question
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
defaultKey Parser (Maybe Bool) -> Bool -> Parser Bool
forall a. Parser (Maybe a) -> a -> Parser a
.!= Bool
False)
    String
"select" -> String -> (Object -> Parser Question) -> Value -> Parser Question
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SelectQuestion"
      (\Object
o -> String -> [String] -> String -> Question
SelectQuestion (String -> [String] -> String -> Question)
-> Parser String -> Parser ([String] -> String -> Question)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
questionKey Parser ([String] -> String -> Question)
-> Parser [String] -> Parser (String -> Question)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe [String])
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
answersKey Parser (Maybe [String]) -> [String] -> Parser [String]
forall a. Parser (Maybe a) -> a -> Parser a
.!= [] Parser (String -> Question) -> Parser String -> Parser Question
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe String)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
defaultKey Parser (Maybe String) -> String -> Parser String
forall a. Parser (Maybe a) -> a -> Parser a
.!= String
"")
    String
"multiselect" -> String -> (Object -> Parser Question) -> Value -> Parser Question
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"MultiselectQuestion"
      (\Object
o -> String -> [String] -> [String] -> Question
MultiselectQuestion (String -> [String] -> [String] -> Question)
-> Parser String -> Parser ([String] -> [String] -> Question)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
questionKey Parser ([String] -> [String] -> Question)
-> Parser [String] -> Parser ([String] -> Question)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe [String])
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
answersKey Parser (Maybe [String]) -> [String] -> Parser [String]
forall a. Parser (Maybe a) -> a -> Parser a
.!= [] Parser ([String] -> Question) -> Parser [String] -> Parser Question
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe [String])
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
defaultKey Parser (Maybe [String]) -> [String] -> Parser [String]
forall a. Parser (Maybe a) -> a -> Parser a
.!= [])
    String
"password" -> String -> (Object -> Parser Question) -> Value -> Parser Question
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Password"
      (\Object
o -> String -> Question
PasswordQuestion (String -> Question) -> Parser String -> Parser Question
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
questionKey)
    String
_ -> String -> (Object -> Parser Question) -> Value -> Parser Question
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"SimpleQuestion"
      (\Object
o -> String -> String -> Question
SimpleQuestion (String -> String -> Question)
-> Parser String -> Parser (String -> Question)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
o Object -> Text -> Parser String
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
questionKey Parser (String -> Question) -> Parser String -> Parser Question
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
o Object -> Text -> Parser (Maybe String)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
defaultKey Parser (Maybe String) -> String -> Parser String
forall a. Parser (Maybe a) -> a -> Parser a
.!= String
"")
  where
    questionKey :: Text
questionKey = Text
"question"
    answersKey :: Text
answersKey = Text
"answers"
    defaultKey :: Text
defaultKey = Text
"default"

-- | Questionnaiere struct
newtype Questionnaire = Questionnaire {
  Questionnaire -> HashMap Text Question
questions :: HashMap Text Question
} deriving ((forall x. Questionnaire -> Rep Questionnaire x)
-> (forall x. Rep Questionnaire x -> Questionnaire)
-> Generic Questionnaire
forall x. Rep Questionnaire x -> Questionnaire
forall x. Questionnaire -> Rep Questionnaire x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Questionnaire x -> Questionnaire
$cfrom :: forall x. Questionnaire -> Rep Questionnaire x
Generic, Int -> Questionnaire -> ShowS
[Questionnaire] -> ShowS
Questionnaire -> String
(Int -> Questionnaire -> ShowS)
-> (Questionnaire -> String)
-> ([Questionnaire] -> ShowS)
-> Show Questionnaire
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Questionnaire] -> ShowS
$cshowList :: [Questionnaire] -> ShowS
show :: Questionnaire -> String
$cshow :: Questionnaire -> String
showsPrec :: Int -> Questionnaire -> ShowS
$cshowsPrec :: Int -> Questionnaire -> ShowS
Show, Questionnaire -> Questionnaire -> Bool
(Questionnaire -> Questionnaire -> Bool)
-> (Questionnaire -> Questionnaire -> Bool) -> Eq Questionnaire
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Questionnaire -> Questionnaire -> Bool
$c/= :: Questionnaire -> Questionnaire -> Bool
== :: Questionnaire -> Questionnaire -> Bool
$c== :: Questionnaire -> Questionnaire -> Bool
Eq)

instance FromJSON Questionnaire

type Blacklist = [(FilePath, [Pattern])]