{-# LANGUAGE OverloadedStrings #-}

module System.Directory.Watchman.Subscribe
    ( SubscriptionName(..)
    , SubscribeParams
    , SubscriptionNotification(..)
    , SubscriptionFiles(..)
    , SubscriptionStateEnter(..)
    , SubscriptionStateLeave(..)
    , renderSubscribe
    , parseSubscriptionNotification

    , since
    , deferVcs
    , defer
    , System.Directory.Watchman.Subscribe.drop
    ) where

import Data.Foldable (foldl')
import Control.Monad (unless)
import Data.ByteString (ByteString)
import Data.Sequence (Seq)
import qualified Data.Sequence as Seq
import qualified Data.Map.Strict as M
import Data.Map.Strict (Map)
import qualified Data.ByteString.Char8 as BC8

import System.Directory.Watchman.WFilePath

import System.Directory.Watchman.Fields
import System.Directory.Watchman.Expression (Expression, renderExpression)
import System.Directory.Watchman.BSER
import System.Directory.Watchman.BSER.Parser
import System.Directory.Watchman.Clockspec
import System.Directory.Watchman.State

data SubscribeParams = SubscribeParams
    { SubscribeParams -> Maybe Clockspec
_SubscribeParams_Since :: !(Maybe Clockspec)
    , SubscribeParams -> Bool
_SubscribeParams_DeferVcs :: !Bool
    , SubscribeParams -> [StateName]
_SubscribeParams_Defer :: ![StateName]
    , SubscribeParams -> [StateName]
_SubscribeParams_Drop :: ![StateName]
    }
    deriving (Int -> SubscribeParams -> ShowS
[SubscribeParams] -> ShowS
SubscribeParams -> String
(Int -> SubscribeParams -> ShowS)
-> (SubscribeParams -> String)
-> ([SubscribeParams] -> ShowS)
-> Show SubscribeParams
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscribeParams] -> ShowS
$cshowList :: [SubscribeParams] -> ShowS
show :: SubscribeParams -> String
$cshow :: SubscribeParams -> String
showsPrec :: Int -> SubscribeParams -> ShowS
$cshowsPrec :: Int -> SubscribeParams -> ShowS
Show, SubscribeParams -> SubscribeParams -> Bool
(SubscribeParams -> SubscribeParams -> Bool)
-> (SubscribeParams -> SubscribeParams -> Bool)
-> Eq SubscribeParams
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscribeParams -> SubscribeParams -> Bool
$c/= :: SubscribeParams -> SubscribeParams -> Bool
== :: SubscribeParams -> SubscribeParams -> Bool
$c== :: SubscribeParams -> SubscribeParams -> Bool
Eq)

defaultSubscribeParams :: SubscribeParams
defaultSubscribeParams :: SubscribeParams
defaultSubscribeParams = SubscribeParams :: Maybe Clockspec
-> Bool -> [StateName] -> [StateName] -> SubscribeParams
SubscribeParams
    { _SubscribeParams_Since :: Maybe Clockspec
_SubscribeParams_Since = Maybe Clockspec
forall a. Maybe a
Nothing
    , _SubscribeParams_DeferVcs :: Bool
_SubscribeParams_DeferVcs = Bool
True
    , _SubscribeParams_Defer :: [StateName]
_SubscribeParams_Defer = []
    , _SubscribeParams_Drop :: [StateName]
_SubscribeParams_Drop = []
    }

newtype SubscriptionName = SubscriptionName ByteString
    deriving (Int -> SubscriptionName -> ShowS
[SubscriptionName] -> ShowS
SubscriptionName -> String
(Int -> SubscriptionName -> ShowS)
-> (SubscriptionName -> String)
-> ([SubscriptionName] -> ShowS)
-> Show SubscriptionName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionName] -> ShowS
$cshowList :: [SubscriptionName] -> ShowS
show :: SubscriptionName -> String
$cshow :: SubscriptionName -> String
showsPrec :: Int -> SubscriptionName -> ShowS
$cshowsPrec :: Int -> SubscriptionName -> ShowS
Show, SubscriptionName -> SubscriptionName -> Bool
(SubscriptionName -> SubscriptionName -> Bool)
-> (SubscriptionName -> SubscriptionName -> Bool)
-> Eq SubscriptionName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionName -> SubscriptionName -> Bool
$c/= :: SubscriptionName -> SubscriptionName -> Bool
== :: SubscriptionName -> SubscriptionName -> Bool
$c== :: SubscriptionName -> SubscriptionName -> Bool
Eq, Eq SubscriptionName
Eq SubscriptionName
-> (SubscriptionName -> SubscriptionName -> Ordering)
-> (SubscriptionName -> SubscriptionName -> Bool)
-> (SubscriptionName -> SubscriptionName -> Bool)
-> (SubscriptionName -> SubscriptionName -> Bool)
-> (SubscriptionName -> SubscriptionName -> Bool)
-> (SubscriptionName -> SubscriptionName -> SubscriptionName)
-> (SubscriptionName -> SubscriptionName -> SubscriptionName)
-> Ord SubscriptionName
SubscriptionName -> SubscriptionName -> Bool
SubscriptionName -> SubscriptionName -> Ordering
SubscriptionName -> SubscriptionName -> SubscriptionName
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 :: SubscriptionName -> SubscriptionName -> SubscriptionName
$cmin :: SubscriptionName -> SubscriptionName -> SubscriptionName
max :: SubscriptionName -> SubscriptionName -> SubscriptionName
$cmax :: SubscriptionName -> SubscriptionName -> SubscriptionName
>= :: SubscriptionName -> SubscriptionName -> Bool
$c>= :: SubscriptionName -> SubscriptionName -> Bool
> :: SubscriptionName -> SubscriptionName -> Bool
$c> :: SubscriptionName -> SubscriptionName -> Bool
<= :: SubscriptionName -> SubscriptionName -> Bool
$c<= :: SubscriptionName -> SubscriptionName -> Bool
< :: SubscriptionName -> SubscriptionName -> Bool
$c< :: SubscriptionName -> SubscriptionName -> Bool
compare :: SubscriptionName -> SubscriptionName -> Ordering
$ccompare :: SubscriptionName -> SubscriptionName -> Ordering
$cp1Ord :: Eq SubscriptionName
Ord)

-- | The subscribe command object allows the client to specify a since parameter; if present in the command,
-- the initial set of subscription results will only include files that changed since the specified clockspec,
-- equivalent to using the @query@ command with the @since@ generator.
--
-- <https://facebook.github.io/watchman/docs/cmd/subscribe.html>
since :: Clockspec -> (SubscribeParams -> SubscribeParams)
since :: Clockspec -> SubscribeParams -> SubscribeParams
since Clockspec
s SubscribeParams
x = SubscribeParams
x { _SubscribeParams_Since :: Maybe Clockspec
_SubscribeParams_Since = Clockspec -> Maybe Clockspec
forall a. a -> Maybe a
Just Clockspec
s }

-- | Starting in watchman version 3.2, after the notification stream is complete, if the root appears to
-- be a version control directory, subscription notifications will be held until an outstanding version
-- control operation is complete (at the time of writing, this is based on the presence of either
-- @.hg/wlock@ or @.git/index.lock@). This behavior matches triggers and helps to avoid performing transient
-- work in response to files changing, for example, during a rebase operation.
--
-- In some circumstances it is desirable for a client to observe the creation of the control files at the start
-- of a version control operation. You may specify that you want this behavior by using 'deferVcs False'
deferVcs :: Bool -> (SubscribeParams -> SubscribeParams)
deferVcs :: Bool -> SubscribeParams -> SubscribeParams
deferVcs Bool
s SubscribeParams
x = SubscribeParams
x { _SubscribeParams_DeferVcs :: Bool
_SubscribeParams_DeferVcs = Bool
s }

defer :: [StateName] -> (SubscribeParams -> SubscribeParams)
defer :: [StateName] -> SubscribeParams -> SubscribeParams
defer [] SubscribeParams
_ = String -> SubscribeParams
forall a. HasCallStack => String -> a
error String
"defer: List of StateNames must not be empty"
defer [StateName]
s SubscribeParams
x = SubscribeParams
x { _SubscribeParams_Defer :: [StateName]
_SubscribeParams_Defer = [StateName]
s }

drop :: [StateName] -> (SubscribeParams -> SubscribeParams)
drop :: [StateName] -> SubscribeParams -> SubscribeParams
drop [] SubscribeParams
_ = String -> SubscribeParams
forall a. HasCallStack => String -> a
error String
"drop: List of StateNames must not be empty"
drop [StateName]
s SubscribeParams
x = SubscribeParams
x { _SubscribeParams_Drop :: [StateName]
_SubscribeParams_Drop = [StateName]
s }

renderSubscribe :: WFilePath -> SubscriptionName -> Expression -> [SubscribeParams -> SubscribeParams] -> [FileFieldLabel] -> BSERValue
renderSubscribe :: WFilePath
-> SubscriptionName
-> Expression
-> [SubscribeParams -> SubscribeParams]
-> [FileFieldLabel]
-> BSERValue
renderSubscribe WFilePath
rootPath (SubscriptionName ByteString
subscriptionName) Expression
expr [SubscribeParams -> SubscribeParams]
params [FileFieldLabel]
fileFieldLabels =
    Seq BSERValue -> BSERValue
BSERArray (Seq BSERValue -> BSERValue) -> Seq BSERValue -> BSERValue
forall a b. (a -> b) -> a -> b
$ [BSERValue] -> Seq BSERValue
forall a. [a] -> Seq a
Seq.fromList
        [ ByteString -> BSERValue
BSERString ByteString
"subscribe"
        , ByteString -> BSERValue
BSERString (WFilePath -> ByteString
toByteString WFilePath
rootPath)
        , ByteString -> BSERValue
BSERString ByteString
subscriptionName
        , Map ByteString BSERValue -> BSERValue
BSERObject (Map ByteString BSERValue -> BSERValue)
-> Map ByteString BSERValue -> BSERValue
forall a b. (a -> b) -> a -> b
$ [Map ByteString BSERValue] -> Map ByteString BSERValue
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
M.unions
            [ [FileFieldLabel] -> Map ByteString BSERValue
renderFieldLabels [FileFieldLabel]
fileFieldLabels
            , ByteString -> BSERValue -> Map ByteString BSERValue
forall k a. k -> a -> Map k a
M.singleton ByteString
"expression" (Expression -> BSERValue
renderExpression Expression
expr)
            , SubscribeParams -> Map ByteString BSERValue
renderSubscribeParams SubscribeParams
params'
            ]
        ]
    where
    params' :: SubscribeParams
params' = (SubscribeParams
 -> (SubscribeParams -> SubscribeParams) -> SubscribeParams)
-> SubscribeParams
-> [SubscribeParams -> SubscribeParams]
-> SubscribeParams
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\SubscribeParams
x SubscribeParams -> SubscribeParams
f -> SubscribeParams -> SubscribeParams
f SubscribeParams
x) SubscribeParams
defaultSubscribeParams [SubscribeParams -> SubscribeParams]
params

renderSubscribeParams :: SubscribeParams -> Map ByteString BSERValue
renderSubscribeParams :: SubscribeParams -> Map ByteString BSERValue
renderSubscribeParams SubscribeParams
params = [Map ByteString BSERValue] -> Map ByteString BSERValue
forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
f (Map k a) -> Map k a
M.unions
    [ case SubscribeParams -> Maybe Clockspec
_SubscribeParams_Since SubscribeParams
params of
        Maybe Clockspec
Nothing -> Map ByteString BSERValue
forall k a. Map k a
M.empty
        Just Clockspec
c -> ByteString -> BSERValue -> Map ByteString BSERValue
forall k a. k -> a -> Map k a
M.singleton ByteString
"since" (Clockspec -> BSERValue
renderClockspec Clockspec
c)
    , case SubscribeParams -> Bool
_SubscribeParams_DeferVcs SubscribeParams
params of
        Bool
True -> Map ByteString BSERValue
forall k a. Map k a
M.empty -- When not specified, default behaviour of watchman is True
        Bool
False -> ByteString -> BSERValue -> Map ByteString BSERValue
forall k a. k -> a -> Map k a
M.singleton ByteString
"defer_vcs" (Bool -> BSERValue
BSERBool Bool
False)
    , case SubscribeParams -> [StateName]
_SubscribeParams_Defer SubscribeParams
params of
        [] -> Map ByteString BSERValue
forall k a. Map k a
M.empty
        [StateName]
xs -> ByteString -> BSERValue -> Map ByteString BSERValue
forall k a. k -> a -> Map k a
M.singleton ByteString
"defer" (Seq BSERValue -> BSERValue
BSERArray ([BSERValue] -> Seq BSERValue
forall a. [a] -> Seq a
Seq.fromList ((StateName -> BSERValue) -> [StateName] -> [BSERValue]
forall a b. (a -> b) -> [a] -> [b]
map (\(StateName ByteString
s) -> ByteString -> BSERValue
BSERString ByteString
s) [StateName]
xs)))
    , case SubscribeParams -> [StateName]
_SubscribeParams_Drop SubscribeParams
params of
        [] -> Map ByteString BSERValue
forall k a. Map k a
M.empty
        [StateName]
xs -> ByteString -> BSERValue -> Map ByteString BSERValue
forall k a. k -> a -> Map k a
M.singleton ByteString
"drop" (Seq BSERValue -> BSERValue
BSERArray ([BSERValue] -> Seq BSERValue
forall a. [a] -> Seq a
Seq.fromList ((StateName -> BSERValue) -> [StateName] -> [BSERValue]
forall a b. (a -> b) -> [a] -> [b]
map (\(StateName ByteString
s) -> ByteString -> BSERValue
BSERString ByteString
s) [StateName]
xs)))
    ]

data SubscriptionFiles = SubscriptionFiles
    { SubscriptionFiles -> ClockId
_SubscriptionFiles_Clock :: !ClockId
    , SubscriptionFiles -> WFilePath
_SubscriptionFiles_Root :: !WFilePath
    , SubscriptionFiles -> SubscriptionName
_SubscriptionFiles_Subscription :: !SubscriptionName
    , SubscriptionFiles -> Seq [FileField]
_SubscriptionFiles_Files :: !(Seq [FileField])
    , SubscriptionFiles -> Bool
_SubscriptionFiles_IsFreshInstance :: !Bool
    }
    deriving (Int -> SubscriptionFiles -> ShowS
[SubscriptionFiles] -> ShowS
SubscriptionFiles -> String
(Int -> SubscriptionFiles -> ShowS)
-> (SubscriptionFiles -> String)
-> ([SubscriptionFiles] -> ShowS)
-> Show SubscriptionFiles
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionFiles] -> ShowS
$cshowList :: [SubscriptionFiles] -> ShowS
show :: SubscriptionFiles -> String
$cshow :: SubscriptionFiles -> String
showsPrec :: Int -> SubscriptionFiles -> ShowS
$cshowsPrec :: Int -> SubscriptionFiles -> ShowS
Show, SubscriptionFiles -> SubscriptionFiles -> Bool
(SubscriptionFiles -> SubscriptionFiles -> Bool)
-> (SubscriptionFiles -> SubscriptionFiles -> Bool)
-> Eq SubscriptionFiles
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c/= :: SubscriptionFiles -> SubscriptionFiles -> Bool
== :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c== :: SubscriptionFiles -> SubscriptionFiles -> Bool
Eq, Eq SubscriptionFiles
Eq SubscriptionFiles
-> (SubscriptionFiles -> SubscriptionFiles -> Ordering)
-> (SubscriptionFiles -> SubscriptionFiles -> Bool)
-> (SubscriptionFiles -> SubscriptionFiles -> Bool)
-> (SubscriptionFiles -> SubscriptionFiles -> Bool)
-> (SubscriptionFiles -> SubscriptionFiles -> Bool)
-> (SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles)
-> (SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles)
-> Ord SubscriptionFiles
SubscriptionFiles -> SubscriptionFiles -> Bool
SubscriptionFiles -> SubscriptionFiles -> Ordering
SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles
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 :: SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles
$cmin :: SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles
max :: SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles
$cmax :: SubscriptionFiles -> SubscriptionFiles -> SubscriptionFiles
>= :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c>= :: SubscriptionFiles -> SubscriptionFiles -> Bool
> :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c> :: SubscriptionFiles -> SubscriptionFiles -> Bool
<= :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c<= :: SubscriptionFiles -> SubscriptionFiles -> Bool
< :: SubscriptionFiles -> SubscriptionFiles -> Bool
$c< :: SubscriptionFiles -> SubscriptionFiles -> Bool
compare :: SubscriptionFiles -> SubscriptionFiles -> Ordering
$ccompare :: SubscriptionFiles -> SubscriptionFiles -> Ordering
$cp1Ord :: Eq SubscriptionFiles
Ord)

data SubscriptionStateEnter = SubscriptionStateEnter
    { SubscriptionStateEnter -> ClockId
_SubscriptionStateEnter_Clock :: !ClockId
    , SubscriptionStateEnter -> WFilePath
_SubscriptionStateEnter_Root :: !WFilePath
    , SubscriptionStateEnter -> SubscriptionName
_SubscriptionStateEnter_Subscription :: !SubscriptionName
    , SubscriptionStateEnter -> StateName
_SubscriptionStateEnter_State :: !StateName
    , SubscriptionStateEnter -> Maybe BSERValue
_SubscriptionStateEnter_Metadata :: !(Maybe BSERValue)
    }
    deriving (Int -> SubscriptionStateEnter -> ShowS
[SubscriptionStateEnter] -> ShowS
SubscriptionStateEnter -> String
(Int -> SubscriptionStateEnter -> ShowS)
-> (SubscriptionStateEnter -> String)
-> ([SubscriptionStateEnter] -> ShowS)
-> Show SubscriptionStateEnter
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionStateEnter] -> ShowS
$cshowList :: [SubscriptionStateEnter] -> ShowS
show :: SubscriptionStateEnter -> String
$cshow :: SubscriptionStateEnter -> String
showsPrec :: Int -> SubscriptionStateEnter -> ShowS
$cshowsPrec :: Int -> SubscriptionStateEnter -> ShowS
Show, SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
(SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> Eq SubscriptionStateEnter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c/= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
== :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c== :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
Eq, Eq SubscriptionStateEnter
Eq SubscriptionStateEnter
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Ordering)
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> (SubscriptionStateEnter -> SubscriptionStateEnter -> Bool)
-> (SubscriptionStateEnter
    -> SubscriptionStateEnter -> SubscriptionStateEnter)
-> (SubscriptionStateEnter
    -> SubscriptionStateEnter -> SubscriptionStateEnter)
-> Ord SubscriptionStateEnter
SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
SubscriptionStateEnter -> SubscriptionStateEnter -> Ordering
SubscriptionStateEnter
-> SubscriptionStateEnter -> SubscriptionStateEnter
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 :: SubscriptionStateEnter
-> SubscriptionStateEnter -> SubscriptionStateEnter
$cmin :: SubscriptionStateEnter
-> SubscriptionStateEnter -> SubscriptionStateEnter
max :: SubscriptionStateEnter
-> SubscriptionStateEnter -> SubscriptionStateEnter
$cmax :: SubscriptionStateEnter
-> SubscriptionStateEnter -> SubscriptionStateEnter
>= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c>= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
> :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c> :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
<= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c<= :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
< :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
$c< :: SubscriptionStateEnter -> SubscriptionStateEnter -> Bool
compare :: SubscriptionStateEnter -> SubscriptionStateEnter -> Ordering
$ccompare :: SubscriptionStateEnter -> SubscriptionStateEnter -> Ordering
$cp1Ord :: Eq SubscriptionStateEnter
Ord)

data SubscriptionStateLeave = SubscriptionStateLeave
    { SubscriptionStateLeave -> ClockId
_SubscriptionStateLeave_Clock :: !ClockId
    , SubscriptionStateLeave -> WFilePath
_SubscriptionStateLeave_Root :: !WFilePath
    , SubscriptionStateLeave -> SubscriptionName
_SubscriptionStateLeave_Subscription :: !SubscriptionName
    , SubscriptionStateLeave -> StateName
_SubscriptionStateLeave_State :: !StateName
    , SubscriptionStateLeave -> Maybe BSERValue
_SubscriptionStateLeave_Metadata :: !(Maybe BSERValue)
    , SubscriptionStateLeave -> Bool
_SubscriptionStateLeave_Abandoned :: !Bool
    }
    deriving (Int -> SubscriptionStateLeave -> ShowS
[SubscriptionStateLeave] -> ShowS
SubscriptionStateLeave -> String
(Int -> SubscriptionStateLeave -> ShowS)
-> (SubscriptionStateLeave -> String)
-> ([SubscriptionStateLeave] -> ShowS)
-> Show SubscriptionStateLeave
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionStateLeave] -> ShowS
$cshowList :: [SubscriptionStateLeave] -> ShowS
show :: SubscriptionStateLeave -> String
$cshow :: SubscriptionStateLeave -> String
showsPrec :: Int -> SubscriptionStateLeave -> ShowS
$cshowsPrec :: Int -> SubscriptionStateLeave -> ShowS
Show, SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
(SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> Eq SubscriptionStateLeave
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c/= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
== :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c== :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
Eq, Eq SubscriptionStateLeave
Eq SubscriptionStateLeave
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Ordering)
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> (SubscriptionStateLeave -> SubscriptionStateLeave -> Bool)
-> (SubscriptionStateLeave
    -> SubscriptionStateLeave -> SubscriptionStateLeave)
-> (SubscriptionStateLeave
    -> SubscriptionStateLeave -> SubscriptionStateLeave)
-> Ord SubscriptionStateLeave
SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
SubscriptionStateLeave -> SubscriptionStateLeave -> Ordering
SubscriptionStateLeave
-> SubscriptionStateLeave -> SubscriptionStateLeave
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 :: SubscriptionStateLeave
-> SubscriptionStateLeave -> SubscriptionStateLeave
$cmin :: SubscriptionStateLeave
-> SubscriptionStateLeave -> SubscriptionStateLeave
max :: SubscriptionStateLeave
-> SubscriptionStateLeave -> SubscriptionStateLeave
$cmax :: SubscriptionStateLeave
-> SubscriptionStateLeave -> SubscriptionStateLeave
>= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c>= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
> :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c> :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
<= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c<= :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
< :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
$c< :: SubscriptionStateLeave -> SubscriptionStateLeave -> Bool
compare :: SubscriptionStateLeave -> SubscriptionStateLeave -> Ordering
$ccompare :: SubscriptionStateLeave -> SubscriptionStateLeave -> Ordering
$cp1Ord :: Eq SubscriptionStateLeave
Ord)

data SubscriptionNotification
    = Subscription_Files !SubscriptionFiles
    | Subscription_StateEnter SubscriptionStateEnter
    | Subscription_StateLeave SubscriptionStateLeave
    deriving (Int -> SubscriptionNotification -> ShowS
[SubscriptionNotification] -> ShowS
SubscriptionNotification -> String
(Int -> SubscriptionNotification -> ShowS)
-> (SubscriptionNotification -> String)
-> ([SubscriptionNotification] -> ShowS)
-> Show SubscriptionNotification
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SubscriptionNotification] -> ShowS
$cshowList :: [SubscriptionNotification] -> ShowS
show :: SubscriptionNotification -> String
$cshow :: SubscriptionNotification -> String
showsPrec :: Int -> SubscriptionNotification -> ShowS
$cshowsPrec :: Int -> SubscriptionNotification -> ShowS
Show, SubscriptionNotification -> SubscriptionNotification -> Bool
(SubscriptionNotification -> SubscriptionNotification -> Bool)
-> (SubscriptionNotification -> SubscriptionNotification -> Bool)
-> Eq SubscriptionNotification
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c/= :: SubscriptionNotification -> SubscriptionNotification -> Bool
== :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c== :: SubscriptionNotification -> SubscriptionNotification -> Bool
Eq, Eq SubscriptionNotification
Eq SubscriptionNotification
-> (SubscriptionNotification
    -> SubscriptionNotification -> Ordering)
-> (SubscriptionNotification -> SubscriptionNotification -> Bool)
-> (SubscriptionNotification -> SubscriptionNotification -> Bool)
-> (SubscriptionNotification -> SubscriptionNotification -> Bool)
-> (SubscriptionNotification -> SubscriptionNotification -> Bool)
-> (SubscriptionNotification
    -> SubscriptionNotification -> SubscriptionNotification)
-> (SubscriptionNotification
    -> SubscriptionNotification -> SubscriptionNotification)
-> Ord SubscriptionNotification
SubscriptionNotification -> SubscriptionNotification -> Bool
SubscriptionNotification -> SubscriptionNotification -> Ordering
SubscriptionNotification
-> SubscriptionNotification -> SubscriptionNotification
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 :: SubscriptionNotification
-> SubscriptionNotification -> SubscriptionNotification
$cmin :: SubscriptionNotification
-> SubscriptionNotification -> SubscriptionNotification
max :: SubscriptionNotification
-> SubscriptionNotification -> SubscriptionNotification
$cmax :: SubscriptionNotification
-> SubscriptionNotification -> SubscriptionNotification
>= :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c>= :: SubscriptionNotification -> SubscriptionNotification -> Bool
> :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c> :: SubscriptionNotification -> SubscriptionNotification -> Bool
<= :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c<= :: SubscriptionNotification -> SubscriptionNotification -> Bool
< :: SubscriptionNotification -> SubscriptionNotification -> Bool
$c< :: SubscriptionNotification -> SubscriptionNotification -> Bool
compare :: SubscriptionNotification -> SubscriptionNotification -> Ordering
$ccompare :: SubscriptionNotification -> SubscriptionNotification -> Ordering
$cp1Ord :: Eq SubscriptionNotification
Ord)

parseSubscriptionNotification :: [FileFieldLabel] -> BSERValue -> Parser SubscriptionNotification
parseSubscriptionNotification :: [FileFieldLabel] -> BSERValue -> Parser SubscriptionNotification
parseSubscriptionNotification [FileFieldLabel]
fileFieldLabels v :: BSERValue
v@(BSERObject Map ByteString BSERValue
o) = do
    case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"files" Map ByteString BSERValue
o of
        Just BSERValue
_ -> do
            SubscriptionFiles
f <- [FileFieldLabel] -> BSERValue -> Parser SubscriptionFiles
parseSubscriptionFiles [FileFieldLabel]
fileFieldLabels BSERValue
v
            SubscriptionNotification -> Parser SubscriptionNotification
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SubscriptionNotification -> Parser SubscriptionNotification)
-> SubscriptionNotification -> Parser SubscriptionNotification
forall a b. (a -> b) -> a -> b
$ SubscriptionFiles -> SubscriptionNotification
Subscription_Files SubscriptionFiles
f
        Maybe BSERValue
Nothing ->
            case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"state-enter" Map ByteString BSERValue
o of
                Just BSERValue
_ -> do
                    SubscriptionStateEnter
s <- BSERValue -> Parser SubscriptionStateEnter
parseSubscriptionStateEnter BSERValue
v
                    SubscriptionNotification -> Parser SubscriptionNotification
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SubscriptionNotification -> Parser SubscriptionNotification)
-> SubscriptionNotification -> Parser SubscriptionNotification
forall a b. (a -> b) -> a -> b
$ SubscriptionStateEnter -> SubscriptionNotification
Subscription_StateEnter SubscriptionStateEnter
s
                Maybe BSERValue
Nothing ->
                    case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"state-leave" Map ByteString BSERValue
o of
                        Just BSERValue
_ -> do
                            SubscriptionStateLeave
s <- BSERValue -> Parser SubscriptionStateLeave
parseSubscriptionStateLeave BSERValue
v
                            SubscriptionNotification -> Parser SubscriptionNotification
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SubscriptionNotification -> Parser SubscriptionNotification)
-> SubscriptionNotification -> Parser SubscriptionNotification
forall a b. (a -> b) -> a -> b
$ SubscriptionStateLeave -> SubscriptionNotification
Subscription_StateLeave SubscriptionStateLeave
s
                        Maybe BSERValue
Nothing ->
                            String -> Parser SubscriptionNotification
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Unrecognized subscription notification"
parseSubscriptionNotification [FileFieldLabel]
_ BSERValue
_ = String -> Parser SubscriptionNotification
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not an Object"

parseSubscriptionFiles :: [FileFieldLabel] -> BSERValue -> Parser SubscriptionFiles
parseSubscriptionFiles :: [FileFieldLabel] -> BSERValue -> Parser SubscriptionFiles
parseSubscriptionFiles [FileFieldLabel]
fileFieldLabels (BSERObject Map ByteString BSERValue
o) = do
    ClockId
clockId <- Map ByteString BSERValue -> Parser ClockId
parseClockId Map ByteString BSERValue
o
    WFilePath
root <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser WFilePath
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"root"
    ByteString
subscription <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"subscription"
    Seq BSERValue
files <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser (Seq BSERValue)
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"files"
    Seq [FileField]
files' <- (BSERValue -> Parser [FileField])
-> Seq BSERValue -> Parser (Seq [FileField])
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM ([FileFieldLabel] -> BSERValue -> Parser [FileField]
parseFileFields [FileFieldLabel]
fileFieldLabels) Seq BSERValue
files
    Bool
isFreshInstance <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser Bool
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"is_fresh_instance"
    SubscriptionFiles -> Parser SubscriptionFiles
forall (f :: * -> *) a. Applicative f => a -> f a
pure SubscriptionFiles :: ClockId
-> WFilePath
-> SubscriptionName
-> Seq [FileField]
-> Bool
-> SubscriptionFiles
SubscriptionFiles
        { _SubscriptionFiles_Clock :: ClockId
_SubscriptionFiles_Clock = ClockId
clockId
        , _SubscriptionFiles_Root :: WFilePath
_SubscriptionFiles_Root = WFilePath
root
        , _SubscriptionFiles_Subscription :: SubscriptionName
_SubscriptionFiles_Subscription = ByteString -> SubscriptionName
SubscriptionName ByteString
subscription
        , _SubscriptionFiles_Files :: Seq [FileField]
_SubscriptionFiles_Files = Seq [FileField]
files'
        , _SubscriptionFiles_IsFreshInstance :: Bool
_SubscriptionFiles_IsFreshInstance = Bool
isFreshInstance
        }
parseSubscriptionFiles [FileFieldLabel]
_ BSERValue
_ = String -> Parser SubscriptionFiles
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not an Object"

parseSubscriptionStateEnter :: BSERValue -> Parser SubscriptionStateEnter
parseSubscriptionStateEnter :: BSERValue -> Parser SubscriptionStateEnter
parseSubscriptionStateEnter (BSERObject Map ByteString BSERValue
o) = do
    ClockId
clockId <- Map ByteString BSERValue -> Parser ClockId
parseClockId Map ByteString BSERValue
o
    WFilePath
root <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser WFilePath
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"root"
    ByteString
subscription <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"subscription"
    ByteString
state <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"state-enter"
    let metadata :: Maybe BSERValue
metadata = case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"metadata" Map ByteString BSERValue
o of
            Maybe BSERValue
Nothing -> Maybe BSERValue
forall a. Maybe a
Nothing
            Just BSERValue
v -> BSERValue -> Maybe BSERValue
forall a. a -> Maybe a
Just BSERValue
v
    SubscriptionStateEnter -> Parser SubscriptionStateEnter
forall (f :: * -> *) a. Applicative f => a -> f a
pure SubscriptionStateEnter :: ClockId
-> WFilePath
-> SubscriptionName
-> StateName
-> Maybe BSERValue
-> SubscriptionStateEnter
SubscriptionStateEnter
      { _SubscriptionStateEnter_Clock :: ClockId
_SubscriptionStateEnter_Clock = ClockId
clockId
      , _SubscriptionStateEnter_Root :: WFilePath
_SubscriptionStateEnter_Root = WFilePath
root
      , _SubscriptionStateEnter_Subscription :: SubscriptionName
_SubscriptionStateEnter_Subscription = ByteString -> SubscriptionName
SubscriptionName ByteString
subscription
      , _SubscriptionStateEnter_State :: StateName
_SubscriptionStateEnter_State = ByteString -> StateName
StateName ByteString
state
      , _SubscriptionStateEnter_Metadata :: Maybe BSERValue
_SubscriptionStateEnter_Metadata = Maybe BSERValue
metadata
      }
parseSubscriptionStateEnter BSERValue
_ = String -> Parser SubscriptionStateEnter
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not an Object"

parseSubscriptionStateLeave :: BSERValue -> Parser SubscriptionStateLeave
parseSubscriptionStateLeave :: BSERValue -> Parser SubscriptionStateLeave
parseSubscriptionStateLeave (BSERObject Map ByteString BSERValue
o) = do
    ClockId
clockId <- Map ByteString BSERValue -> Parser ClockId
parseClockId Map ByteString BSERValue
o
    WFilePath
root <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser WFilePath
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"root"
    ByteString
subscription <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"subscription"
    ByteString
state <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"state-leave"
    let metadata :: Maybe BSERValue
metadata = case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"metadata" Map ByteString BSERValue
o of
            Maybe BSERValue
Nothing -> Maybe BSERValue
forall a. Maybe a
Nothing
            Just BSERValue
v -> BSERValue -> Maybe BSERValue
forall a. a -> Maybe a
Just BSERValue
v
    let abandoned :: Bool
abandoned = case ByteString -> Map ByteString BSERValue -> Maybe BSERValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup ByteString
"abandoned" Map ByteString BSERValue
o of
            Just (BSERBool Bool
True) -> Bool
True
            Maybe BSERValue
_ -> Bool
False
    SubscriptionStateLeave -> Parser SubscriptionStateLeave
forall (f :: * -> *) a. Applicative f => a -> f a
pure SubscriptionStateLeave :: ClockId
-> WFilePath
-> SubscriptionName
-> StateName
-> Maybe BSERValue
-> Bool
-> SubscriptionStateLeave
SubscriptionStateLeave
      { _SubscriptionStateLeave_Clock :: ClockId
_SubscriptionStateLeave_Clock = ClockId
clockId
      , _SubscriptionStateLeave_Root :: WFilePath
_SubscriptionStateLeave_Root = WFilePath
root
      , _SubscriptionStateLeave_Subscription :: SubscriptionName
_SubscriptionStateLeave_Subscription = ByteString -> SubscriptionName
SubscriptionName ByteString
subscription
      , _SubscriptionStateLeave_State :: StateName
_SubscriptionStateLeave_State = ByteString -> StateName
StateName ByteString
state
      , _SubscriptionStateLeave_Metadata :: Maybe BSERValue
_SubscriptionStateLeave_Metadata = Maybe BSERValue
metadata
      , _SubscriptionStateLeave_Abandoned :: Bool
_SubscriptionStateLeave_Abandoned = Bool
abandoned
      }
parseSubscriptionStateLeave BSERValue
_ = String -> Parser SubscriptionStateLeave
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not an Object"

parseClockId :: BSERObject -> Parser ClockId
parseClockId :: Map ByteString BSERValue -> Parser ClockId
parseClockId Map ByteString BSERValue
o = do
    ByteString
clockId <- Map ByteString BSERValue
o Map ByteString BSERValue -> ByteString -> Parser ByteString
forall a.
FromBSER a =>
Map ByteString BSERValue -> ByteString -> Parser a
.: ByteString
"clock"
    Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ByteString
"c:" ByteString -> ByteString -> Bool
`BC8.isPrefixOf` ByteString
clockId) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$
        String -> Parser ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser ()) -> String -> Parser ()
forall a b. (a -> b) -> a -> b
$ String
"Invalid clock id: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
BC8.unpack ByteString
clockId
    ClockId -> Parser ClockId
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> ClockId
ClockId ByteString
clockId)