-- | The Mask module models the state a recurring parent saves about its child tasks.
module Taskwarrior.Mask
  ( Mask(..)
  , MaskState
  )
where

import qualified Data.Text                     as Text
import qualified Data.Aeson                    as Aeson
import qualified Data.Aeson.Types              as Aeson.Types

-- | Represents the state of a child in a 'Status.Recurring' 'Task.Task'.
data MaskState = Pending | Completed | Deleted | Waiting deriving (MaskState -> MaskState -> Bool
(MaskState -> MaskState -> Bool)
-> (MaskState -> MaskState -> Bool) -> Eq MaskState
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MaskState -> MaskState -> Bool
$c/= :: MaskState -> MaskState -> Bool
== :: MaskState -> MaskState -> Bool
$c== :: MaskState -> MaskState -> Bool
Eq, Int -> MaskState -> ShowS
[MaskState] -> ShowS
MaskState -> String
(Int -> MaskState -> ShowS)
-> (MaskState -> String)
-> ([MaskState] -> ShowS)
-> Show MaskState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MaskState] -> ShowS
$cshowList :: [MaskState] -> ShowS
show :: MaskState -> String
$cshow :: MaskState -> String
showsPrec :: Int -> MaskState -> ShowS
$cshowsPrec :: Int -> MaskState -> ShowS
Show, Int -> MaskState
MaskState -> Int
MaskState -> [MaskState]
MaskState -> MaskState
MaskState -> MaskState -> [MaskState]
MaskState -> MaskState -> MaskState -> [MaskState]
(MaskState -> MaskState)
-> (MaskState -> MaskState)
-> (Int -> MaskState)
-> (MaskState -> Int)
-> (MaskState -> [MaskState])
-> (MaskState -> MaskState -> [MaskState])
-> (MaskState -> MaskState -> [MaskState])
-> (MaskState -> MaskState -> MaskState -> [MaskState])
-> Enum MaskState
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: MaskState -> MaskState -> MaskState -> [MaskState]
$cenumFromThenTo :: MaskState -> MaskState -> MaskState -> [MaskState]
enumFromTo :: MaskState -> MaskState -> [MaskState]
$cenumFromTo :: MaskState -> MaskState -> [MaskState]
enumFromThen :: MaskState -> MaskState -> [MaskState]
$cenumFromThen :: MaskState -> MaskState -> [MaskState]
enumFrom :: MaskState -> [MaskState]
$cenumFrom :: MaskState -> [MaskState]
fromEnum :: MaskState -> Int
$cfromEnum :: MaskState -> Int
toEnum :: Int -> MaskState
$ctoEnum :: Int -> MaskState
pred :: MaskState -> MaskState
$cpred :: MaskState -> MaskState
succ :: MaskState -> MaskState
$csucc :: MaskState -> MaskState
Enum, ReadPrec [MaskState]
ReadPrec MaskState
Int -> ReadS MaskState
ReadS [MaskState]
(Int -> ReadS MaskState)
-> ReadS [MaskState]
-> ReadPrec MaskState
-> ReadPrec [MaskState]
-> Read MaskState
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [MaskState]
$creadListPrec :: ReadPrec [MaskState]
readPrec :: ReadPrec MaskState
$creadPrec :: ReadPrec MaskState
readList :: ReadS [MaskState]
$creadList :: ReadS [MaskState]
readsPrec :: Int -> ReadS MaskState
$creadsPrec :: Int -> ReadS MaskState
Read, Eq MaskState
Eq MaskState
-> (MaskState -> MaskState -> Ordering)
-> (MaskState -> MaskState -> Bool)
-> (MaskState -> MaskState -> Bool)
-> (MaskState -> MaskState -> Bool)
-> (MaskState -> MaskState -> Bool)
-> (MaskState -> MaskState -> MaskState)
-> (MaskState -> MaskState -> MaskState)
-> Ord MaskState
MaskState -> MaskState -> Bool
MaskState -> MaskState -> Ordering
MaskState -> MaskState -> MaskState
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 :: MaskState -> MaskState -> MaskState
$cmin :: MaskState -> MaskState -> MaskState
max :: MaskState -> MaskState -> MaskState
$cmax :: MaskState -> MaskState -> MaskState
>= :: MaskState -> MaskState -> Bool
$c>= :: MaskState -> MaskState -> Bool
> :: MaskState -> MaskState -> Bool
$c> :: MaskState -> MaskState -> Bool
<= :: MaskState -> MaskState -> Bool
$c<= :: MaskState -> MaskState -> Bool
< :: MaskState -> MaskState -> Bool
$c< :: MaskState -> MaskState -> Bool
compare :: MaskState -> MaskState -> Ordering
$ccompare :: MaskState -> MaskState -> Ordering
$cp1Ord :: Eq MaskState
Ord, MaskState
MaskState -> MaskState -> Bounded MaskState
forall a. a -> a -> Bounded a
maxBound :: MaskState
$cmaxBound :: MaskState
minBound :: MaskState
$cminBound :: MaskState
Bounded)

-- | The mask is a newtype to provide 'Data.Aeson' instances from and to a JSON string.
newtype Mask = Mask {Mask -> [MaskState]
mask :: [MaskState]} deriving (Mask -> Mask -> Bool
(Mask -> Mask -> Bool) -> (Mask -> Mask -> Bool) -> Eq Mask
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mask -> Mask -> Bool
$c/= :: Mask -> Mask -> Bool
== :: Mask -> Mask -> Bool
$c== :: Mask -> Mask -> Bool
Eq, ReadPrec [Mask]
ReadPrec Mask
Int -> ReadS Mask
ReadS [Mask]
(Int -> ReadS Mask)
-> ReadS [Mask] -> ReadPrec Mask -> ReadPrec [Mask] -> Read Mask
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Mask]
$creadListPrec :: ReadPrec [Mask]
readPrec :: ReadPrec Mask
$creadPrec :: ReadPrec Mask
readList :: ReadS [Mask]
$creadList :: ReadS [Mask]
readsPrec :: Int -> ReadS Mask
$creadsPrec :: Int -> ReadS Mask
Read, Eq Mask
Eq Mask
-> (Mask -> Mask -> Ordering)
-> (Mask -> Mask -> Bool)
-> (Mask -> Mask -> Bool)
-> (Mask -> Mask -> Bool)
-> (Mask -> Mask -> Bool)
-> (Mask -> Mask -> Mask)
-> (Mask -> Mask -> Mask)
-> Ord Mask
Mask -> Mask -> Bool
Mask -> Mask -> Ordering
Mask -> Mask -> Mask
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 :: Mask -> Mask -> Mask
$cmin :: Mask -> Mask -> Mask
max :: Mask -> Mask -> Mask
$cmax :: Mask -> Mask -> Mask
>= :: Mask -> Mask -> Bool
$c>= :: Mask -> Mask -> Bool
> :: Mask -> Mask -> Bool
$c> :: Mask -> Mask -> Bool
<= :: Mask -> Mask -> Bool
$c<= :: Mask -> Mask -> Bool
< :: Mask -> Mask -> Bool
$c< :: Mask -> Mask -> Bool
compare :: Mask -> Mask -> Ordering
$ccompare :: Mask -> Mask -> Ordering
$cp1Ord :: Eq Mask
Ord, Int -> Mask -> ShowS
[Mask] -> ShowS
Mask -> String
(Int -> Mask -> ShowS)
-> (Mask -> String) -> ([Mask] -> ShowS) -> Show Mask
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Mask] -> ShowS
$cshowList :: [Mask] -> ShowS
show :: Mask -> String
$cshow :: Mask -> String
showsPrec :: Int -> Mask -> ShowS
$cshowsPrec :: Int -> Mask -> ShowS
Show)

toChar :: MaskState -> Char
toChar :: MaskState -> Char
toChar = \case
  MaskState
Pending   -> Char
'-'
  MaskState
Completed -> Char
'+'
  MaskState
Deleted   -> Char
'X'
  MaskState
Waiting   -> Char
'W'

instance Aeson.FromJSON Mask where
  parseJSON :: Value -> Parser Mask
parseJSON =
    String -> (Text -> Parser Mask) -> Value -> Parser Mask
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"Mask" ((Text -> Parser Mask) -> Value -> Parser Mask)
-> (Text -> Parser Mask) -> Value -> Parser Mask
forall a b. (a -> b) -> a -> b
$ ([MaskState] -> Mask) -> Parser [MaskState] -> Parser Mask
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [MaskState] -> Mask
Mask (Parser [MaskState] -> Parser Mask)
-> (Text -> Parser [MaskState]) -> Text -> Parser Mask
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Parser MaskState) -> String -> Parser [MaskState]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Char -> Parser MaskState
parseChar (String -> Parser [MaskState])
-> (Text -> String) -> Text -> Parser [MaskState]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack

parseChar :: Char -> Aeson.Types.Parser MaskState
parseChar :: Char -> Parser MaskState
parseChar = \case
  Char
'-'  -> MaskState -> Parser MaskState
forall (f :: * -> *) a. Applicative f => a -> f a
pure MaskState
Pending
  Char
'+'  -> MaskState -> Parser MaskState
forall (f :: * -> *) a. Applicative f => a -> f a
pure MaskState
Completed
  Char
'X'  -> MaskState -> Parser MaskState
forall (f :: * -> *) a. Applicative f => a -> f a
pure MaskState
Deleted
  Char
'W'  -> MaskState -> Parser MaskState
forall (f :: * -> *) a. Applicative f => a -> f a
pure MaskState
Waiting
  Char
char -> String -> Parser MaskState
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser MaskState) -> String -> Parser MaskState
forall a b. (a -> b) -> a -> b
$ String
"Not a Mask Char: '" String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
char] String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"'"

instance Aeson.ToJSON Mask where
  toJSON :: Mask -> Value
toJSON = Text -> Value
Aeson.String (Text -> Value) -> (Mask -> Text) -> Mask -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Text) -> (Mask -> String) -> Mask -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (MaskState -> Char) -> [MaskState] -> String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MaskState -> Char
toChar ([MaskState] -> String) -> (Mask -> [MaskState]) -> Mask -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mask -> [MaskState]
mask