module Taskwarrior.Status
( Status(..)
, parseFromObject
, toPairs
)
where
import Taskwarrior.Mask ( Mask )
import qualified Taskwarrior.Time as Time
import Data.Aeson ( Object
, (.:)
, (.=)
, ToJSON
, FromJSON
, pairs
, object
, withObject
)
import qualified Data.Aeson as Aeson
import Data.Text ( Text )
import Data.Time ( UTCTime )
import Data.Aeson.Types ( Parser
, typeMismatch
, Pair
)
data Status =
Pending |
Deleted { end :: UTCTime } |
Completed { end :: UTCTime } |
Waiting { wait :: UTCTime } |
Recurring {
recur :: Text,
mask :: Mask}
deriving (Eq, Show, Read, Ord)
parseFromObject :: Object -> Parser Status
parseFromObject o = (o .: "status") >>= \case
"pending" -> pure Pending
"deleted" -> Deleted <$> (o .: "end" >>= Time.parse)
"completed" -> Completed <$> (o .: "end" >>= Time.parse)
"waiting" -> Waiting <$> (o .: "wait" >>= Time.parse)
"recurring" -> Recurring <$> o .: "recur" <*> o .: "mask"
str -> typeMismatch "status" (Aeson.String str)
toPairs :: Status -> [Pair]
toPairs = \case
Pending -> [statusLabel "pending"]
Deleted {..} -> [statusLabel "deleted", "end" .= Time.toValue end]
Completed {..} -> [statusLabel "completed", "end" .= Time.toValue end]
Waiting {..} -> [statusLabel "waiting", "wait" .= Time.toValue wait]
Recurring {..} -> [statusLabel "recurring", "recur" .= recur, "mask" .= mask]
where
statusLabel :: Text -> Pair
statusLabel = ("status" .=)
instance FromJSON Status where
parseJSON = withObject "Status" parseFromObject
instance ToJSON Status where
toJSON = object . toPairs
toEncoding = pairs . mconcat . map (uncurry (.=)) . toPairs