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

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

-- | Represents the state of a child in a 'Status.Recurring' 'Task.Task'.
data MaskState = Pending | Completed | Deleted | Waiting deriving (MaskState -> MaskState -> Bool
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 -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [MaskState] -> ShowS
$cshowList :: [MaskState] -> ShowS
show :: MaskState -> [Char]
$cshow :: MaskState -> [Char]
showsPrec :: Int -> MaskState -> ShowS
$cshowsPrec :: Int -> MaskState -> ShowS
Show, Int -> MaskState
MaskState -> Int
MaskState -> [MaskState]
MaskState -> MaskState
MaskState -> MaskState -> [MaskState]
MaskState -> MaskState -> MaskState -> [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]
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
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
Ord, 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
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]
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
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
Ord, Int -> Mask -> ShowS
[Mask] -> ShowS
Mask -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Mask] -> ShowS
$cshowList :: [Mask] -> ShowS
show :: Mask -> [Char]
$cshow :: Mask -> [Char]
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 =
    forall a. [Char] -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText [Char]
"Mask" forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [MaskState] -> Mask
Mask forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Char -> Parser MaskState
parseChar forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
Text.unpack

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

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