{-# LANGUAGE DataKinds      #-}
{-# LANGUAGE GADTs          #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies   #-}
--------------------------------------------------------------------------------
-- |
-- Module : Database.EventStore.Internal.Operation.Read.Common
-- Copyright : (C) 2015 Yorick Laupa
-- License : (see the file LICENSE)
--
-- Maintainer : Yorick Laupa <yo.eight@gmail.com>
-- Stability : provisional
-- Portability : non-portable
--
--------------------------------------------------------------------------------
module Database.EventStore.Internal.Operation.Read.Common where

--------------------------------------------------------------------------------
import Control.Applicative
import Data.Foldable
import Data.Maybe (isNothing)
import Data.Monoid
import Data.Traversable

--------------------------------------------------------------------------------
import Database.EventStore.Internal.Prelude
import Database.EventStore.Internal.Stream
import Database.EventStore.Internal.Types

--------------------------------------------------------------------------------
import Prelude

--------------------------------------------------------------------------------
-- | Enumeration detailing the possible outcomes of reading a stream.
data ReadResult t a where
    ReadSuccess       :: a -> ReadResult t a
    ReadNoStream      :: ReadResult EventNumber a
    ReadStreamDeleted :: StreamName -> ReadResult EventNumber a
    ReadNotModified   :: ReadResult t a
    ReadError         :: Maybe Text -> ReadResult t a
    ReadAccessDenied  :: StreamId t -> ReadResult t a

--------------------------------------------------------------------------------
instance Eq a => Eq (ReadResult t a) where
    ReadSuccess a
a       == :: ReadResult t a -> ReadResult t a -> Bool
== ReadSuccess a
b       = a
a forall a. Eq a => a -> a -> Bool
== a
b
    ReadResult t a
ReadNoStream        == ReadResult t a
ReadNoStream        = Bool
True
    ReadStreamDeleted StreamName
s == ReadStreamDeleted StreamName
v = StreamName
s forall a. Eq a => a -> a -> Bool
== StreamName
v
    ReadResult t a
ReadNotModified     == ReadResult t a
ReadNotModified     = Bool
True
    ReadError Maybe Text
e         == ReadError Maybe Text
u         = Maybe Text
e forall a. Eq a => a -> a -> Bool
== Maybe Text
u
    ReadAccessDenied StreamId t
s  == ReadAccessDenied StreamId t
v  = StreamId t
s forall a. Eq a => a -> a -> Bool
== StreamId t
v
    ReadResult t a
_                   == ReadResult t a
_                   = Bool
False

--------------------------------------------------------------------------------
instance Show a => Show (ReadResult t a) where
    show :: ReadResult t a -> String
show (ReadSuccess a
a)       = String
"ReadSuccess " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
a
    show ReadResult t a
ReadNoStream          = String
"ReadNoStream"
    show (ReadStreamDeleted StreamName
s) = String
"ReadStreamDeleted" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show StreamName
s
    show ReadResult t a
ReadNotModified       = String
"ReadNoModified"
    show (ReadError Maybe Text
e)         = String
"ReadError" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show Maybe Text
e
    show (ReadAccessDenied StreamId t
s)  = String
"ReadAccessDenied " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show StreamId t
s

--------------------------------------------------------------------------------
instance Functor (ReadResult t) where
    fmap :: forall a b. (a -> b) -> ReadResult t a -> ReadResult t b
fmap a -> b
f (ReadSuccess a
a)       = forall a t. a -> ReadResult t a
ReadSuccess (a -> b
f a
a)
    fmap a -> b
_ ReadResult t a
ReadNoStream          = forall a. ReadResult EventNumber a
ReadNoStream
    fmap a -> b
_ (ReadStreamDeleted StreamName
s) = forall a. StreamName -> ReadResult EventNumber a
ReadStreamDeleted StreamName
s
    fmap a -> b
_ ReadResult t a
ReadNotModified       = forall t a. ReadResult t a
ReadNotModified
    fmap a -> b
_ (ReadError Maybe Text
e)         = forall t a. Maybe Text -> ReadResult t a
ReadError Maybe Text
e
    fmap a -> b
_ (ReadAccessDenied StreamId t
s)  = forall t a. StreamId t -> ReadResult t a
ReadAccessDenied StreamId t
s

--------------------------------------------------------------------------------
instance Foldable (ReadResult t) where
    foldMap :: forall m a. Monoid m => (a -> m) -> ReadResult t a -> m
foldMap a -> m
f (ReadSuccess a
a) = a -> m
f a
a
    foldMap a -> m
_ ReadResult t a
_               = forall a. Monoid a => a
mempty

--------------------------------------------------------------------------------
instance Traversable (ReadResult t) where
    traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ReadResult t a -> f (ReadResult t b)
traverse a -> f b
f (ReadSuccess a
a)       = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a t. a -> ReadResult t a
ReadSuccess forall a b. (a -> b) -> a -> b
$ a -> f b
f a
a
    traverse a -> f b
_ ReadResult t a
ReadNoStream          = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. ReadResult EventNumber a
ReadNoStream
    traverse a -> f b
_ (ReadStreamDeleted StreamName
s) = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. StreamName -> ReadResult EventNumber a
ReadStreamDeleted StreamName
s
    traverse a -> f b
_ ReadResult t a
ReadNotModified       = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall t a. ReadResult t a
ReadNotModified
    traverse a -> f b
_ (ReadError Maybe Text
e)         = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall t a. Maybe Text -> ReadResult t a
ReadError Maybe Text
e
    traverse a -> f b
_ (ReadAccessDenied StreamId t
s)  = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall t a. StreamId t -> ReadResult t a
ReadAccessDenied StreamId t
s

--------------------------------------------------------------------------------
-- | Gathers common slice operations.
data Slice t
    = SliceEndOfStream
    | Slice ![ResolvedEvent] !(Maybe t)
    deriving Int -> Slice t -> ShowS
forall t. Show t => Int -> Slice t -> ShowS
forall t. Show t => [Slice t] -> ShowS
forall t. Show t => Slice t -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Slice t] -> ShowS
$cshowList :: forall t. Show t => [Slice t] -> ShowS
show :: Slice t -> String
$cshow :: forall t. Show t => Slice t -> String
showsPrec :: Int -> Slice t -> ShowS
$cshowsPrec :: forall t. Show t => Int -> Slice t -> ShowS
Show

--------------------------------------------------------------------------------
-- | Empty slice.
emptySlice :: Slice t
emptySlice :: forall t. Slice t
emptySlice = forall t. Slice t
SliceEndOfStream

--------------------------------------------------------------------------------
instance Functor Slice where
    fmap :: forall a b. (a -> b) -> Slice a -> Slice b
fmap a -> b
_ Slice a
SliceEndOfStream = forall t. Slice t
SliceEndOfStream
    fmap a -> b
f (Slice [ResolvedEvent]
xs Maybe a
next)  = forall t. [ResolvedEvent] -> Maybe t -> Slice t
Slice [ResolvedEvent]
xs (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f Maybe a
next)

--------------------------------------------------------------------------------
-- | Gets slice's 'ResolvedEvents's.
sliceEvents :: Slice t -> [ResolvedEvent]
sliceEvents :: forall t. Slice t -> [ResolvedEvent]
sliceEvents Slice t
SliceEndOfStream = []
sliceEvents (Slice [ResolvedEvent]
xs Maybe t
_)     = [ResolvedEvent]
xs

--------------------------------------------------------------------------------
-- | If the slice has reached the end of the stream.
sliceEOS :: Slice t -> Bool
sliceEOS :: forall t. Slice t -> Bool
sliceEOS Slice t
SliceEndOfStream = Bool
True
sliceEOS (Slice [ResolvedEvent]
_ Maybe t
next)   = forall a. Maybe a -> Bool
isNothing Maybe t
next

--------------------------------------------------------------------------------
-- | Gets the next location of this slice.
sliceNext :: Slice t -> Maybe t
sliceNext :: forall t. Slice t -> Maybe t
sliceNext Slice t
SliceEndOfStream = forall a. Maybe a
Nothing
sliceNext (Slice [ResolvedEvent]
_ Maybe t
next)   = Maybe t
next

--------------------------------------------------------------------------------
-- | Regular stream slice.
type StreamSlice = Slice EventNumber

--------------------------------------------------------------------------------
-- | Represents a slice of the $all stream.
type AllSlice = Slice Position