{-# LANGUAGE BlockArguments #-}

module Data.RdsData.Encode.Row
  ( EncodeRow(..)

  , rdsValue

  , column

  , maybe

  , array
  , bool
  , bytestring
  , double
  , integer
  , null
  , text

  , base64
  , day
  , int
  , int8
  , int16
  , int32
  , int64
  , json
  , lazyBytestring
  , lazyText
  , timeOfDay
  , ulid
  , utcTime
  , uuid
  , word
  , word8
  , word16
  , word32
  , word64
  ) where

import Data.ByteString (ByteString)
import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divisible
import Data.Int
import Data.RdsData.Encode.Array (EncodeArray(..))
import Data.RdsData.Encode.Value (EncodeValue(..))
import Data.RdsData.Types.Value
import Data.Text (Text)
import Data.Time
import Data.ULID (ULID)
import Data.UUID (UUID)
import Data.Void
import Data.Word
import Prelude hiding (maybe, null)

import qualified Amazonka.Data.Base64       as AWS
import qualified Data.Aeson                 as J
import qualified Data.ByteString.Lazy       as LBS
import qualified Data.RdsData.Encode.Value  as EV
import qualified Data.Text.Lazy             as LT
import qualified Prelude                    as P

newtype EncodeRow a = EncodeRow
  { forall a. EncodeRow a -> a -> [Value] -> [Value]
encodeRow :: a -> [Value] -> [Value]
  }

instance Contravariant EncodeRow where
  contramap :: forall a' a. (a' -> a) -> EncodeRow a -> EncodeRow a'
contramap a' -> a
f (EncodeRow a -> [Value] -> [Value]
g) =
    (a' -> [Value] -> [Value]) -> EncodeRow a'
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow (a -> [Value] -> [Value]
g (a -> [Value] -> [Value]) -> (a' -> a) -> a' -> [Value] -> [Value]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a' -> a
f)

instance Divisible EncodeRow where
  divide :: forall a b c.
(a -> (b, c)) -> EncodeRow b -> EncodeRow c -> EncodeRow a
divide a -> (b, c)
f (EncodeRow b -> [Value] -> [Value]
g) (EncodeRow c -> [Value] -> [Value]
h) =
    (a -> [Value] -> [Value]) -> EncodeRow a
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow \a
a ->
      case a -> (b, c)
f a
a of
        (b
b, c
c) -> b -> [Value] -> [Value]
g b
b ([Value] -> [Value]) -> ([Value] -> [Value]) -> [Value] -> [Value]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. c -> [Value] -> [Value]
h c
c
  conquer :: forall a. EncodeRow a
conquer =
    (a -> [Value] -> [Value]) -> EncodeRow a
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow ((a -> [Value] -> [Value]) -> EncodeRow a)
-> (a -> [Value] -> [Value]) -> EncodeRow a
forall a b. (a -> b) -> a -> b
$ ([Value] -> [Value]) -> a -> [Value] -> [Value]
forall a b. a -> b -> a
const [Value] -> [Value]
forall a. a -> a
id

instance Decidable EncodeRow where
  choose :: forall a b c.
(a -> Either b c) -> EncodeRow b -> EncodeRow c -> EncodeRow a
choose a -> Either b c
f (EncodeRow b -> [Value] -> [Value]
g) (EncodeRow c -> [Value] -> [Value]
h) =
    (a -> [Value] -> [Value]) -> EncodeRow a
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow \a
a ->
      case a -> Either b c
f a
a of
        Left b
b -> b -> [Value] -> [Value]
g b
b
        Right c
c -> c -> [Value] -> [Value]
h c
c
  lose :: forall a. (a -> Void) -> EncodeRow a
lose a -> Void
f =
    (a -> [Value] -> [Value]) -> EncodeRow a
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow ((a -> [Value] -> [Value]) -> EncodeRow a)
-> (a -> [Value] -> [Value]) -> EncodeRow a
forall a b. (a -> b) -> a -> b
$ Void -> [Value] -> [Value]
forall a. Void -> a
absurd (Void -> [Value] -> [Value])
-> (a -> Void) -> a -> [Value] -> [Value]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Void
f

--------------------------------------------------------------------------------

rdsValue :: EncodeRow Value
rdsValue :: EncodeRow Value
rdsValue =
  (Value -> [Value] -> [Value]) -> EncodeRow Value
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow (:)

--------------------------------------------------------------------------------

column :: EncodeValue a -> EncodeRow a
column :: forall a. EncodeValue a -> EncodeRow a
column (EncodeValue a -> Value
f) =
  (a -> [Value] -> [Value]) -> EncodeRow a
forall a. (a -> [Value] -> [Value]) -> EncodeRow a
EncodeRow \a
a -> (a -> Value
f a
aValue -> [Value] -> [Value]
forall a. a -> [a] -> [a]
:)

--------------------------------------------------------------------------------

maybe :: EncodeRow a -> EncodeRow (Maybe a)
maybe :: forall a. EncodeRow a -> EncodeRow (Maybe a)
maybe =
  (Maybe a -> Either () a)
-> EncodeRow () -> EncodeRow a -> EncodeRow (Maybe a)
forall a b c.
(a -> Either b c) -> EncodeRow b -> EncodeRow c -> EncodeRow a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose (Either () a -> (a -> Either () a) -> Maybe a -> Either () a
forall b a. b -> (a -> b) -> Maybe a -> b
P.maybe (() -> Either () a
forall a b. a -> Either a b
Left ()) a -> Either () a
forall a b. b -> Either a b
Right) EncodeRow ()
null

--------------------------------------------------------------------------------

array :: EncodeArray a -> EncodeRow a
array :: forall a. EncodeArray a -> EncodeRow a
array =
  EncodeValue a -> EncodeRow a
forall a. EncodeValue a -> EncodeRow a
column (EncodeValue a -> EncodeRow a)
-> (EncodeArray a -> EncodeValue a) -> EncodeArray a -> EncodeRow a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EncodeArray a -> EncodeValue a
forall a. EncodeArray a -> EncodeValue a
EV.array

base64 :: EncodeRow AWS.Base64
base64 :: EncodeRow Base64
base64 =
  EncodeValue Base64 -> EncodeRow Base64
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Base64
EV.base64

bool :: EncodeRow Bool
bool :: EncodeRow Bool
bool =
  EncodeValue Bool -> EncodeRow Bool
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Bool
EV.bool

double :: EncodeRow Double
double :: EncodeRow Double
double =
  EncodeValue Double -> EncodeRow Double
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Double
EV.double

null :: EncodeRow ()
null :: EncodeRow ()
null =
  EncodeValue () -> EncodeRow ()
forall a. EncodeValue a -> EncodeRow a
column EncodeValue ()
EV.null

integer :: EncodeRow Integer
integer :: EncodeRow Integer
integer =
  EncodeValue Integer -> EncodeRow Integer
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Integer
EV.integer

text :: EncodeRow Text
text :: EncodeRow Text
text =
  EncodeValue Text -> EncodeRow Text
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Text
EV.text

--------------------------------------------------------------------------------

int :: EncodeRow Int
int :: EncodeRow Int
int =
  EncodeValue Int -> EncodeRow Int
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Int
EV.int

int8 :: EncodeRow Int8
int8 :: EncodeRow Int8
int8 =
  EncodeValue Int8 -> EncodeRow Int8
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Int8
EV.int8

int16 :: EncodeRow Int16
int16 :: EncodeRow Int16
int16 =
  EncodeValue Int16 -> EncodeRow Int16
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Int16
EV.int16

int32 :: EncodeRow Int32
int32 :: EncodeRow Int32
int32 =
  EncodeValue Int32 -> EncodeRow Int32
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Int32
EV.int32

int64 :: EncodeRow Int64
int64 :: EncodeRow Int64
int64 =
  EncodeValue Int64 -> EncodeRow Int64
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Int64
EV.int64

word :: EncodeRow Word
word :: EncodeRow Word
word =
  EncodeValue Word -> EncodeRow Word
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Word
EV.word

word8 :: EncodeRow Word8
word8 :: EncodeRow Word8
word8 =
  EncodeValue Word8 -> EncodeRow Word8
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Word8
EV.word8

word16 :: EncodeRow Word16
word16 :: EncodeRow Word16
word16 =
  EncodeValue Word16 -> EncodeRow Word16
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Word16
EV.word16

word32 :: EncodeRow Word32
word32 :: EncodeRow Word32
word32 =
  EncodeValue Word32 -> EncodeRow Word32
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Word32
EV.word32

word64 :: EncodeRow Word64
word64 :: EncodeRow Word64
word64 =
  EncodeValue Word64 -> EncodeRow Word64
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Word64
EV.word64

lazyText :: EncodeRow LT.Text
lazyText :: EncodeRow Text
lazyText =
  EncodeValue Text -> EncodeRow Text
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Text
EV.lazyText

bytestring :: EncodeRow ByteString
bytestring :: EncodeRow ByteString
bytestring =
  EncodeValue ByteString -> EncodeRow ByteString
forall a. EncodeValue a -> EncodeRow a
column EncodeValue ByteString
EV.bytestring

lazyBytestring :: EncodeRow LBS.ByteString
lazyBytestring :: EncodeRow ByteString
lazyBytestring =
  EncodeValue ByteString -> EncodeRow ByteString
forall a. EncodeValue a -> EncodeRow a
column EncodeValue ByteString
EV.lazyBytestring

timeOfDay :: EncodeRow TimeOfDay
timeOfDay :: EncodeRow TimeOfDay
timeOfDay =
  EncodeValue TimeOfDay -> EncodeRow TimeOfDay
forall a. EncodeValue a -> EncodeRow a
column EncodeValue TimeOfDay
EV.timeOfDay

day :: EncodeRow Day
day :: EncodeRow Day
day =
  EncodeValue Day -> EncodeRow Day
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Day
EV.day

json :: EncodeRow J.Value
json :: EncodeRow Value
json =
  EncodeValue Value -> EncodeRow Value
forall a. EncodeValue a -> EncodeRow a
column EncodeValue Value
EV.json

ulid :: EncodeRow ULID
ulid :: EncodeRow ULID
ulid =
  EncodeValue ULID -> EncodeRow ULID
forall a. EncodeValue a -> EncodeRow a
column EncodeValue ULID
EV.ulid

utcTime :: EncodeRow UTCTime
utcTime :: EncodeRow UTCTime
utcTime =
  EncodeValue UTCTime -> EncodeRow UTCTime
forall a. EncodeValue a -> EncodeRow a
column EncodeValue UTCTime
EV.utcTime

uuid :: EncodeRow UUID
uuid :: EncodeRow UUID
uuid =
  EncodeValue UUID -> EncodeRow UUID
forall a. EncodeValue a -> EncodeRow a
column EncodeValue UUID
EV.uuid