{-# LANGUAGE DeriveGeneric   #-}
{-# LANGUAGE TemplateHaskell #-}

module AWSLambda.Events where

import           Control.Applicative           ((<|>))
import           Control.Lens.TH
import           Data.Aeson                    (FromJSON (..), Value)
import           Network.AWS.Data.Text         (FromText)

import           AWSLambda.Events.KinesisEvent
import           AWSLambda.Events.S3Event
import           AWSLambda.Events.SNSEvent

-- | Not yet implemented
data DynamoDBEvent

-- | Not yet implemented
data SESEvent

-- | Not yet implemented
data CognitoEvent

-- | Not yet implemented
data CloudFormationEvent

-- | Not yet implemented
data CloudWatchLogsEvent

-- | Not yet implemented
data CloudWatchEventsEvent

-- | Not yet implemented
data CodeCommitEvent

-- | Not yet implemented
data ConfigEvent

-- | Not yet implemented
data AlexaEvent

-- | Not yet implemented
data LexEvent

-- | Not yet implemented
data APIGatewayEvent

-- | Not yet implemented
data IoTButtonEvent

-- | Not yet implemented
data CloudFrontEvent

-- | Not yet implemented
data FirehoseEvent

-- | Not yet implemented
data InvokeEvent

-- | Sum type for all possible Lambda events.
-- Parameterised on the type of SNS Events to be handled.
-- See @SNSEvent@ for details.
data LambdaEvent snsMessage
  = S3 !S3Event
  | DynamoDB !DynamoDBEvent
  | KinesisStream !KinesisEvent
  | SNS !(SNSEvent snsMessage)
  | SES !SESEvent
  | Cognito !CognitoEvent
  | CloudFormation !CloudFormationEvent
  | CloudWatchLogs !CloudWatchLogsEvent
  | CloudWatchEvents !CloudWatchEventsEvent
  | CodeCommit !CodeCommitEvent
  | Config !ConfigEvent
  | Alexa !AlexaEvent
  | Lex !LexEvent
  | APIGateway !APIGatewayEvent
  | IoTButton !IoTButtonEvent
  | CloudFront !CloudFrontEvent
  | Firehose !FirehoseEvent
  | Invoke !InvokeEvent
  | Custom !Value

-- | Attempt to parse the various event types.
-- Any valid JSON that can't be parsed as a specific
-- event type will result in a 'Custom' value.
instance FromText snsMessage =>
         FromJSON (LambdaEvent snsMessage) where
  parseJSON :: Value -> Parser (LambdaEvent snsMessage)
parseJSON Value
v =
    (S3Event -> LambdaEvent snsMessage)
-> Value -> Parser (LambdaEvent snsMessage)
forall a b. FromJSON a => (a -> b) -> Value -> Parser b
try S3Event -> LambdaEvent snsMessage
forall snsMessage. S3Event -> LambdaEvent snsMessage
S3 Value
v Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (KinesisEvent -> LambdaEvent snsMessage)
-> Value -> Parser (LambdaEvent snsMessage)
forall a b. FromJSON a => (a -> b) -> Value -> Parser b
try KinesisEvent -> LambdaEvent snsMessage
forall snsMessage. KinesisEvent -> LambdaEvent snsMessage
KinesisStream Value
v Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (SNSEvent snsMessage -> LambdaEvent snsMessage)
-> Value -> Parser (LambdaEvent snsMessage)
forall a b. FromJSON a => (a -> b) -> Value -> Parser b
try SNSEvent snsMessage -> LambdaEvent snsMessage
forall snsMessage. SNSEvent snsMessage -> LambdaEvent snsMessage
SNS Value
v Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
-> Parser (LambdaEvent snsMessage)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> LambdaEvent snsMessage -> Parser (LambdaEvent snsMessage)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value -> LambdaEvent snsMessage
forall snsMessage. Value -> LambdaEvent snsMessage
Custom Value
v)
    where
      try :: (a -> b) -> Value -> Parser b
try a -> b
f = (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Parser a -> Parser b) -> (Value -> Parser a) -> Value -> Parser b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON

$(makePrisms ''LambdaEvent)