{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Web.TwitchAPI.Helix.ChannelPoints where

import Prelude

import qualified Data.ByteString.Char8 as BS
import qualified Data.Time             as Time
import qualified Data.Time.RFC3339     as Time ( parseTimeRFC3339 )
import qualified Data.Text             as Text
import qualified Network.HTTP.Client   as HTTP

import Data.Maybe ( fromMaybe )
import Data.Aeson ( FromJSON(..), (.:), withObject
                  , ToJSON(..), (.=), object, encode
                  , Object
                  )

import qualified Web.TwitchAPI.Helix.Request as Req

class RewardDetails a where
    broadcasterId :: a -> Integer
    prompt :: a -> Maybe String
    backgroundColor :: a -> String
    maxPerStream :: a -> Maybe Integer
    maxPerUser :: a -> Maybe Integer
    autoFulfilled :: a -> Bool

data Create = Create { Create -> Integer
forBroadcasterId :: Integer
                     , Create -> String
title :: String
                     , Create -> Maybe String
setPrompt :: Maybe String
                     , Create -> Integer
cost :: Integer
                     , Create -> Maybe Bool
enabled :: Maybe Bool
                     , Create -> Maybe String
setBackgroundColor :: Maybe String
                     , Create -> Maybe Integer
setMaxPerStream :: Maybe Integer
                     , Create -> Maybe Integer
setMaxPerUser :: Maybe Integer
                     , Create -> Maybe Integer
cooldownSeconds :: Maybe Integer
                     , Create -> Maybe Bool
setAutoFulfilled :: Maybe Bool
                     } deriving ( Int -> Create -> ShowS
[Create] -> ShowS
Create -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Create] -> ShowS
$cshowList :: [Create] -> ShowS
show :: Create -> String
$cshow :: Create -> String
showsPrec :: Int -> Create -> ShowS
$cshowsPrec :: Int -> Create -> ShowS
Show, Create -> Create -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Create -> Create -> Bool
$c/= :: Create -> Create -> Bool
== :: Create -> Create -> Bool
$c== :: Create -> Create -> Bool
Eq )

instance ToJSON Create where
    toJSON :: Create -> Value
toJSON Create{Integer
String
Maybe Bool
Maybe Integer
Maybe String
setAutoFulfilled :: Maybe Bool
cooldownSeconds :: Maybe Integer
setMaxPerUser :: Maybe Integer
setMaxPerStream :: Maybe Integer
setBackgroundColor :: Maybe String
enabled :: Maybe Bool
cost :: Integer
setPrompt :: Maybe String
title :: String
forBroadcasterId :: Integer
setAutoFulfilled :: Create -> Maybe Bool
cooldownSeconds :: Create -> Maybe Integer
setMaxPerUser :: Create -> Maybe Integer
setMaxPerStream :: Create -> Maybe Integer
setBackgroundColor :: Create -> Maybe String
enabled :: Create -> Maybe Bool
cost :: Create -> Integer
setPrompt :: Create -> Maybe String
title :: Create -> String
forBroadcasterId :: Create -> Integer
..} =
        [Pair] -> Value
object [ Key
"title"      forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= String -> Text
Text.pack String
title
               , Key
"prompt"     forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (String -> Text
Text.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
setPrompt)
               , Key
"cost"       forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Integer
cost
               , Key
"is_enabled" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a. a -> Maybe a -> a
fromMaybe Bool
True Maybe Bool
enabled
               , Key
"background_color" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= (String -> Text
Text.pack forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe String
setBackgroundColor)
               , Key
"is_user_input_required" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const Bool
True) Maybe String
setPrompt
               , Key
"is_max_per_stream_enabled" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const Bool
True) Maybe Integer
setMaxPerStream
               , Key
"max_per_stream" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
setMaxPerStream
               , Key
"is_max_per_user_per_stream_enabled" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const Bool
True) Maybe Integer
setMaxPerUser
               , Key
"max_per_user_per_stream" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
setMaxPerUser
               , Key
"is_global_cooldown_enabled" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b. a -> b -> a
const Bool
True) Maybe Integer
cooldownSeconds
               , Key
"global_cooldown_seconds" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
cooldownSeconds
               , Key
"should_redemptions_skip_request_queue" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Bool
setAutoFulfilled
               ]

instance Req.HelixRequest Create where
    toRequest :: Create -> Request
toRequest Create
create =
        let setQuery :: Request -> Request
setQuery  = [(ByteString, Maybe ByteString)] -> Request -> Request
HTTP.setQueryString [(ByteString
"broadcaster_id", forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BS.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show forall a b. (a -> b) -> a -> b
$ (forall a. RewardDetails a => a -> Integer
broadcasterId :: Create -> Integer) Create
create)]
            setBody :: Request -> Request
setBody Request
r = Request
r{ requestBody :: RequestBody
HTTP.requestBody = ByteString -> RequestBody
HTTP.RequestBodyLBS forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> ByteString
encode forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. ToJSON a => a -> Value
toJSON forall a b. (a -> b) -> a -> b
$ Create
create }
        in Request -> Request
setBody forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> Request
setQuery forall a b. (a -> b) -> a -> b
$ String -> Request
HTTP.parseRequest_ String
"POST https://api.twitch.tv/helix/channel_points/custom_rewards"
    scope :: Create -> Maybe String
scope Create{} = forall a. a -> Maybe a
Just String
"channel:manage:redemptions"

instance RewardDetails Create where
    broadcasterId :: Create -> Integer
broadcasterId = Create -> Integer
forBroadcasterId
    prompt :: Create -> Maybe String
prompt = Create -> Maybe String
setPrompt
    backgroundColor :: Create -> String
backgroundColor = forall a. a -> Maybe a -> a
fromMaybe String
"" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Create -> Maybe String
setBackgroundColor
    maxPerStream :: Create -> Maybe Integer
maxPerStream = Create -> Maybe Integer
setMaxPerStream
    maxPerUser :: Create -> Maybe Integer
maxPerUser = Create -> Maybe Integer
setMaxPerUser
    autoFulfilled :: Create -> Bool
autoFulfilled = forall a. a -> Maybe a -> a
fromMaybe Bool
False forall b c a. (b -> c) -> (a -> b) -> a -> c
. Create -> Maybe Bool
setAutoFulfilled

data RewardImages = RewardImages { RewardImages -> Maybe String
tiny :: Maybe String
                                 , RewardImages -> Maybe String
large :: Maybe String
                                 , RewardImages -> Maybe String
huge :: Maybe String
                                 } deriving ( Int -> RewardImages -> ShowS
[RewardImages] -> ShowS
RewardImages -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [RewardImages] -> ShowS
$cshowList :: [RewardImages] -> ShowS
show :: RewardImages -> String
$cshow :: RewardImages -> String
showsPrec :: Int -> RewardImages -> ShowS
$cshowsPrec :: Int -> RewardImages -> ShowS
Show, RewardImages -> RewardImages -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: RewardImages -> RewardImages -> Bool
$c/= :: RewardImages -> RewardImages -> Bool
== :: RewardImages -> RewardImages -> Bool
$c== :: RewardImages -> RewardImages -> Bool
Eq )

instance FromJSON RewardImages where
    parseJSON :: Value -> Parser RewardImages
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"RewardImages" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        Maybe String
tiny <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"url_1x"
        Maybe String
large <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"url_2x"
        Maybe String
huge <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"url_4x"
        forall (m :: * -> *) a. Monad m => a -> m a
return RewardImages{Maybe String
huge :: Maybe String
large :: Maybe String
tiny :: Maybe String
huge :: Maybe String
large :: Maybe String
tiny :: Maybe String
..}

data CreateResponse = CreateResponse { CreateResponse -> Integer
broadcaster :: Integer
                                     , CreateResponse -> String
broadcasterLogin :: String
                                     , CreateResponse -> String
broadcasterName :: String
                                     , CreateResponse -> String
rewardId :: String
                                     , CreateResponse -> String
rewardTitle :: String
                                     , CreateResponse -> Maybe String
rewardPrompt :: Maybe String
                                     , CreateResponse -> Integer
rewardCost :: Integer
                                     , CreateResponse -> Maybe RewardImages
rewardImage :: Maybe RewardImages
                                     , CreateResponse -> RewardImages
defaultImage :: RewardImages
                                     , CreateResponse -> String
rewardBackgroundColor :: String
                                     , CreateResponse -> Maybe Integer
rewardMaxPerStream :: Maybe Integer
                                     , CreateResponse -> Maybe Integer
rewardMaxPerUser :: Maybe Integer
                                     , CreateResponse -> Maybe Integer
cooldown :: Maybe Integer
                                     , CreateResponse -> Bool
paused :: Bool
                                     , CreateResponse -> Bool
inStock :: Bool
                                     , CreateResponse -> Bool
rewardAutoFulfilled :: Bool
                                     , CreateResponse -> Integer
redemptionCount :: Integer
                                     , CreateResponse -> Maybe UTCTime
cooldownExpires :: Maybe Time.UTCTime
                                     } deriving ( Int -> CreateResponse -> ShowS
[CreateResponse] -> ShowS
CreateResponse -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CreateResponse] -> ShowS
$cshowList :: [CreateResponse] -> ShowS
show :: CreateResponse -> String
$cshow :: CreateResponse -> String
showsPrec :: Int -> CreateResponse -> ShowS
$cshowsPrec :: Int -> CreateResponse -> ShowS
Show, CreateResponse -> CreateResponse -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CreateResponse -> CreateResponse -> Bool
$c/= :: CreateResponse -> CreateResponse -> Bool
== :: CreateResponse -> CreateResponse -> Bool
$c== :: CreateResponse -> CreateResponse -> Bool
Eq )

instance FromJSON CreateResponse where
    parseJSON :: Value -> Parser CreateResponse
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"CreateResponse" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        String
bid <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"broadcaster_id"
        let broadcaster :: Integer
broadcaster = forall a. Read a => String -> a
read String
bid :: Integer
        String
broadcasterLogin <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"broadcaster_login"
        String
broadcasterName <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"broadcaster_name"
        String
rewardId <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
        String
rewardTitle <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"title"

        String
promptText <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"prompt"
        Bool
promptEnabled :: Bool <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_user_input_required"
        let rewardPrompt :: Maybe String
rewardPrompt = if Bool
promptEnabled then forall a. a -> Maybe a
Just String
promptText else forall a. Maybe a
Nothing

        Integer
rewardCost <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cost"
        Maybe RewardImages
rewardImage <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"image"
        RewardImages
defaultImage <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"default_image"
        String
rewardBackgroundColor <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"background_color"

        Object
maxObject :: Object <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"max_per_stream_setting"
        Bool
maxEnabled <- Object
maxObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_enabled"
        Integer
streamMax <- Object
maxObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"max_per_stream"
        let rewardMaxPerStream :: Maybe Integer
rewardMaxPerStream = if Bool
maxEnabled then forall a. a -> Maybe a
Just Integer
streamMax else forall a. Maybe a
Nothing

        Object
userMaxObject :: Object <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"max_per_user_per_stream_setting"
        Bool
userMaxEnabled <- Object
userMaxObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_enabled"
        Integer
userMax <- Object
userMaxObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"max_per_user_per_stream"
        let rewardMaxPerUser :: Maybe Integer
rewardMaxPerUser = if Bool
userMaxEnabled then forall a. a -> Maybe a
Just Integer
userMax else forall a. Maybe a
Nothing

        Object
cooldownObject :: Object <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"global_cooldown_setting"
        Bool
cooldownEnabled <- Object
cooldownObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_enabled"
        Integer
cooldownSeconds <- Object
cooldownObject forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"global_cooldown_seconds"
        let cooldown :: Maybe Integer
cooldown = if Bool
cooldownEnabled then forall a. a -> Maybe a
Just Integer
cooldownSeconds else forall a. Maybe a
Nothing

        Bool
paused <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_paused"
        Bool
inStock <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"is_in_stock"
        Bool
rewardAutoFulfilled <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"should_redemptions_skip_request_queue"
        Integer
redemptionCount <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"redemptions_redeemed_current_stream"
        Maybe String
cooldownExpiry :: Maybe String <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"cooldown_expires_at"
        let cooldownExpires :: Maybe UTCTime
cooldownExpires = ZonedTime -> UTCTime
Time.zonedTimeToUTC forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall t. TextualMonoid t => t -> Maybe ZonedTime
Time.parseTimeRFC3339 forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe String
cooldownExpiry)
        forall (m :: * -> *) a. Monad m => a -> m a
return CreateResponse{Bool
Integer
String
Maybe Integer
Maybe String
Maybe UTCTime
Maybe RewardImages
RewardImages
cooldownExpires :: Maybe UTCTime
redemptionCount :: Integer
rewardAutoFulfilled :: Bool
inStock :: Bool
paused :: Bool
cooldown :: Maybe Integer
rewardMaxPerUser :: Maybe Integer
rewardMaxPerStream :: Maybe Integer
rewardBackgroundColor :: String
defaultImage :: RewardImages
rewardImage :: Maybe RewardImages
rewardCost :: Integer
rewardPrompt :: Maybe String
rewardTitle :: String
rewardId :: String
broadcasterName :: String
broadcasterLogin :: String
broadcaster :: Integer
cooldownExpires :: Maybe UTCTime
redemptionCount :: Integer
rewardAutoFulfilled :: Bool
inStock :: Bool
paused :: Bool
cooldown :: Maybe Integer
rewardMaxPerUser :: Maybe Integer
rewardMaxPerStream :: Maybe Integer
rewardBackgroundColor :: String
defaultImage :: RewardImages
rewardImage :: Maybe RewardImages
rewardCost :: Integer
rewardPrompt :: Maybe String
rewardTitle :: String
rewardId :: String
broadcasterName :: String
broadcasterLogin :: String
broadcaster :: Integer
..}

instance RewardDetails CreateResponse where
    broadcasterId :: CreateResponse -> Integer
broadcasterId = CreateResponse -> Integer
broadcaster
    prompt :: CreateResponse -> Maybe String
prompt = CreateResponse -> Maybe String
rewardPrompt
    backgroundColor :: CreateResponse -> String
backgroundColor = CreateResponse -> String
rewardBackgroundColor
    maxPerStream :: CreateResponse -> Maybe Integer
maxPerStream = CreateResponse -> Maybe Integer
rewardMaxPerStream
    maxPerUser :: CreateResponse -> Maybe Integer
maxPerUser = CreateResponse -> Maybe Integer
rewardMaxPerUser
    autoFulfilled :: CreateResponse -> Bool
autoFulfilled = CreateResponse -> Bool
rewardAutoFulfilled