{-# LANGUAGE DataKinds      #-}
{-# LANGUAGE GADTs          #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies   #-}
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
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       == ReadSuccess b       = a == b
    ReadNoStream        == ReadNoStream        = True
    ReadStreamDeleted s == ReadStreamDeleted v = s == v
    ReadNotModified     == ReadNotModified     = True
    ReadError e         == ReadError u         = e == u
    ReadAccessDenied s  == ReadAccessDenied v  = s == v
    _                   == _                   = False
instance Show a => Show (ReadResult t a) where
    show (ReadSuccess a)       = "ReadSuccess " ++ show a
    show ReadNoStream          = "ReadNoStream"
    show (ReadStreamDeleted s) = "ReadStreamDeleted" ++ show s
    show ReadNotModified       = "ReadNoModified"
    show (ReadError e)         = "ReadError" ++ show e
    show (ReadAccessDenied s)  = "ReadAccessDenied " ++ show s
instance Functor (ReadResult t) where
    fmap f (ReadSuccess a)       = ReadSuccess (f a)
    fmap _ ReadNoStream          = ReadNoStream
    fmap _ (ReadStreamDeleted s) = ReadStreamDeleted s
    fmap _ ReadNotModified       = ReadNotModified
    fmap _ (ReadError e)         = ReadError e
    fmap _ (ReadAccessDenied s)  = ReadAccessDenied s
instance Foldable (ReadResult t) where
    foldMap f (ReadSuccess a) = f a
    foldMap _ _               = mempty
instance Traversable (ReadResult t) where
    traverse f (ReadSuccess a)       = fmap ReadSuccess $ f a
    traverse _ ReadNoStream          = pure ReadNoStream
    traverse _ (ReadStreamDeleted s) = pure $ ReadStreamDeleted s
    traverse _ ReadNotModified       = pure ReadNotModified
    traverse _ (ReadError e)         = pure $ ReadError e
    traverse _ (ReadAccessDenied s)  = pure $ ReadAccessDenied s
data Slice t
    = SliceEndOfStream
    | Slice ![ResolvedEvent] !(Maybe t)
    deriving Show
emptySlice :: Slice t
emptySlice = SliceEndOfStream
instance Functor Slice where
    fmap _ SliceEndOfStream = SliceEndOfStream
    fmap f (Slice xs next)  = Slice xs (fmap f next)
sliceEvents :: Slice t -> [ResolvedEvent]
sliceEvents SliceEndOfStream = []
sliceEvents (Slice xs _)     = xs
sliceEOS :: Slice t -> Bool
sliceEOS SliceEndOfStream = True
sliceEOS (Slice _ next)   = isNothing next
sliceNext :: Slice t -> Maybe t
sliceNext SliceEndOfStream = Nothing
sliceNext (Slice _ next)   = next
type StreamSlice = Slice EventNumber
type AllSlice = Slice Position