module Jerimum.Storage.PostgreSQL.Schemas.EventType
  ( EventTypeSchema(..)
  , EventTypeEnum(..)
  , Version
  , digest
  ) where

import qualified Crypto.Hash.SHA256                as SHA256
import qualified Data.ByteString                   as B
import           Data.ByteString.Builder
import qualified Data.ByteString.Lazy              as L
import           Data.Monoid
import qualified Data.Text                         as T
import           Data.Text.Encoding
import qualified Jerimum.PostgreSQL.Types          as J
import qualified Jerimum.PostgreSQL.Types.Encoding as E

type Version = B.ByteString

data EventTypeSchema
  = TableSchema { schemaName :: T.Text
                , tableName  :: T.Text
                , fieldset   :: [(T.Text, J.CBORValue)] }
  | MessageSchema { transactional :: Bool
                  , namespace     :: T.Text }
  deriving (Show)

data EventTypeEnum
  = EventTypeTable
  | EventTypeMessage
  deriving (Show, Eq, Enum)

encodeFieldset :: [(T.Text, J.CBORValue)] -> Builder
encodeFieldset [] = mempty
encodeFieldset ((name, tyinfo):fieldset) =
  let codedTyInfo = lazyByteString $ E.toLazyByteString tyinfo
  in encodeUtf8Builder name <> codedTyInfo <> encodeFieldset fieldset

digest :: EventTypeSchema -> Version
digest (TableSchema schema table fieldset) =
  SHA256.finalize $
  SHA256.updates
    SHA256.init
    [ B.singleton 1
    , encodeUtf8 schema
    , encodeUtf8 table
    , L.toStrict $ toLazyByteString $ encodeFieldset fieldset
    ]
digest (MessageSchema tx ns) =
  SHA256.finalize $
  SHA256.updates
    SHA256.init
    [ B.singleton 0
    , B.singleton
        (if tx
           then 0
           else 1)
    , encodeUtf8 ns
    ]
