{-# LANGUAGE DeriveGeneric #-}

module Server.Core where

import Core
import GHC.Generics
import Network.HTTP.Client (Manager)
import qualified Database.Redis as Redis
import qualified Data.Aeson as A
import qualified Data.Map as M
import qualified Data.Text as T

data EnvironmentType = EnvironmentTypeDev | EnvironmentTypeProd
    deriving (EnvironmentType -> EnvironmentType -> Bool
(EnvironmentType -> EnvironmentType -> Bool)
-> (EnvironmentType -> EnvironmentType -> Bool)
-> Eq EnvironmentType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: EnvironmentType -> EnvironmentType -> Bool
== :: EnvironmentType -> EnvironmentType -> Bool
$c/= :: EnvironmentType -> EnvironmentType -> Bool
/= :: EnvironmentType -> EnvironmentType -> Bool
Eq, Int -> EnvironmentType -> ShowS
[EnvironmentType] -> ShowS
EnvironmentType -> String
(Int -> EnvironmentType -> ShowS)
-> (EnvironmentType -> String)
-> ([EnvironmentType] -> ShowS)
-> Show EnvironmentType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> EnvironmentType -> ShowS
showsPrec :: Int -> EnvironmentType -> ShowS
$cshow :: EnvironmentType -> String
show :: EnvironmentType -> String
$cshowList :: [EnvironmentType] -> ShowS
showList :: [EnvironmentType] -> ShowS
Show)

data IdentityProvider = IdentityProvider
    { IdentityProvider -> Text
identityProviderIdentifier :: T.Text
    , IdentityProvider -> Text
identityProviderName :: T.Text
    , IdentityProvider -> Text
identityProviderLoginUrl :: T.Text
    }

data ServerConfiguration = ServerConfiguration
    { ServerConfiguration -> EnvironmentType
serverConfigurationEnvironmentType :: EnvironmentType
    , ServerConfiguration -> [IdentityProvider]
serverConfigurationIdentityProviders :: [IdentityProvider]
    , ServerConfiguration -> Maybe String
serverConfigurationRedisHostname :: Maybe String
    , ServerConfiguration -> Maybe String
serverConfigurationOpenIdMicrosoftClientId :: Maybe String
    , ServerConfiguration -> Maybe String
serverConfigurationOpenIdMicrosoftClientSecret :: Maybe String
    }

data ServerResources = ServerResources
    { ServerResources -> Manager
serverResourcesTlsManager :: Manager
    , ServerResources -> Connection
serverResourcesRedisConnection :: Redis.Connection
    }

data UserIdentifier = UserIdentifier
    { UserIdentifier -> Text
userIdentifierProvider :: T.Text
    , UserIdentifier -> Text
userIdentifierSubject :: T.Text -- Must be unique per provider
    }

data UserIdentity = UserIdentity
    { UserIdentity -> UserIdentifier
userIdentifier :: UserIdentifier
    , UserIdentity -> Text
userPictureUrl :: T.Text
    , UserIdentity -> Text
userName :: T.Text
    }

data DeckPreferences = DeckPreferences
    { DeckPreferences -> Map Text CardPreferences
cardPreferences :: M.Map T.Text CardPreferences
    } deriving ((forall x. DeckPreferences -> Rep DeckPreferences x)
-> (forall x. Rep DeckPreferences x -> DeckPreferences)
-> Generic DeckPreferences
forall x. Rep DeckPreferences x -> DeckPreferences
forall x. DeckPreferences -> Rep DeckPreferences x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. DeckPreferences -> Rep DeckPreferences x
from :: forall x. DeckPreferences -> Rep DeckPreferences x
$cto :: forall x. Rep DeckPreferences x -> DeckPreferences
to :: forall x. Rep DeckPreferences x -> DeckPreferences
Generic, Int -> DeckPreferences -> ShowS
[DeckPreferences] -> ShowS
DeckPreferences -> String
(Int -> DeckPreferences -> ShowS)
-> (DeckPreferences -> String)
-> ([DeckPreferences] -> ShowS)
-> Show DeckPreferences
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DeckPreferences -> ShowS
showsPrec :: Int -> DeckPreferences -> ShowS
$cshow :: DeckPreferences -> String
show :: DeckPreferences -> String
$cshowList :: [DeckPreferences] -> ShowS
showList :: [DeckPreferences] -> ShowS
Show)

data CardStatus = CardCurrentlyLearning | CardAlreadyMastered | CardNotStarted
    deriving (CardStatus -> CardStatus -> Bool
(CardStatus -> CardStatus -> Bool)
-> (CardStatus -> CardStatus -> Bool) -> Eq CardStatus
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CardStatus -> CardStatus -> Bool
== :: CardStatus -> CardStatus -> Bool
$c/= :: CardStatus -> CardStatus -> Bool
/= :: CardStatus -> CardStatus -> Bool
Eq, (forall x. CardStatus -> Rep CardStatus x)
-> (forall x. Rep CardStatus x -> CardStatus) -> Generic CardStatus
forall x. Rep CardStatus x -> CardStatus
forall x. CardStatus -> Rep CardStatus x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CardStatus -> Rep CardStatus x
from :: forall x. CardStatus -> Rep CardStatus x
$cto :: forall x. Rep CardStatus x -> CardStatus
to :: forall x. Rep CardStatus x -> CardStatus
Generic, Int -> CardStatus -> ShowS
[CardStatus] -> ShowS
CardStatus -> String
(Int -> CardStatus -> ShowS)
-> (CardStatus -> String)
-> ([CardStatus] -> ShowS)
-> Show CardStatus
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CardStatus -> ShowS
showsPrec :: Int -> CardStatus -> ShowS
$cshow :: CardStatus -> String
show :: CardStatus -> String
$cshowList :: [CardStatus] -> ShowS
showList :: [CardStatus] -> ShowS
Show)

data CardPreferences = CardPreferences
    { CardPreferences -> CardStatus
cardStatus :: CardStatus
    } deriving ((forall x. CardPreferences -> Rep CardPreferences x)
-> (forall x. Rep CardPreferences x -> CardPreferences)
-> Generic CardPreferences
forall x. Rep CardPreferences x -> CardPreferences
forall x. CardPreferences -> Rep CardPreferences x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CardPreferences -> Rep CardPreferences x
from :: forall x. CardPreferences -> Rep CardPreferences x
$cto :: forall x. Rep CardPreferences x -> CardPreferences
to :: forall x. Rep CardPreferences x -> CardPreferences
Generic, Int -> CardPreferences -> ShowS
[CardPreferences] -> ShowS
CardPreferences -> String
(Int -> CardPreferences -> ShowS)
-> (CardPreferences -> String)
-> ([CardPreferences] -> ShowS)
-> Show CardPreferences
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CardPreferences -> ShowS
showsPrec :: Int -> CardPreferences -> ShowS
$cshow :: CardPreferences -> String
show :: CardPreferences -> String
$cshowList :: [CardPreferences] -> ShowS
showList :: [CardPreferences] -> ShowS
Show)

data DeckProficiency = DeckProficiency
    { DeckProficiency -> Map Text CardProficiency
cardProficiencies :: M.Map T.Text CardProficiency
    } deriving ((forall x. DeckProficiency -> Rep DeckProficiency x)
-> (forall x. Rep DeckProficiency x -> DeckProficiency)
-> Generic DeckProficiency
forall x. Rep DeckProficiency x -> DeckProficiency
forall x. DeckProficiency -> Rep DeckProficiency x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. DeckProficiency -> Rep DeckProficiency x
from :: forall x. DeckProficiency -> Rep DeckProficiency x
$cto :: forall x. Rep DeckProficiency x -> DeckProficiency
to :: forall x. Rep DeckProficiency x -> DeckProficiency
Generic, Int -> DeckProficiency -> ShowS
[DeckProficiency] -> ShowS
DeckProficiency -> String
(Int -> DeckProficiency -> ShowS)
-> (DeckProficiency -> String)
-> ([DeckProficiency] -> ShowS)
-> Show DeckProficiency
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> DeckProficiency -> ShowS
showsPrec :: Int -> DeckProficiency -> ShowS
$cshow :: DeckProficiency -> String
show :: DeckProficiency -> String
$cshowList :: [DeckProficiency] -> ShowS
showList :: [DeckProficiency] -> ShowS
Show)

data CardProficiency = CardProficiency
    { CardProficiency -> [Bool]
lastAttempts :: [Bool]
    } deriving ((forall x. CardProficiency -> Rep CardProficiency x)
-> (forall x. Rep CardProficiency x -> CardProficiency)
-> Generic CardProficiency
forall x. Rep CardProficiency x -> CardProficiency
forall x. CardProficiency -> Rep CardProficiency x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CardProficiency -> Rep CardProficiency x
from :: forall x. CardProficiency -> Rep CardProficiency x
$cto :: forall x. Rep CardProficiency x -> CardProficiency
to :: forall x. Rep CardProficiency x -> CardProficiency
Generic, Int -> CardProficiency -> ShowS
[CardProficiency] -> ShowS
CardProficiency -> String
(Int -> CardProficiency -> ShowS)
-> (CardProficiency -> String)
-> ([CardProficiency] -> ShowS)
-> Show CardProficiency
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CardProficiency -> ShowS
showsPrec :: Int -> CardProficiency -> ShowS
$cshow :: CardProficiency -> String
show :: CardProficiency -> String
$cshowList :: [CardProficiency] -> ShowS
showList :: [CardProficiency] -> ShowS
Show)

data CardWithUserFeatures = CardWithUserFeatures
    { CardWithUserFeatures -> Card
card :: Card
    , CardWithUserFeatures -> Int
cardProficiencyWeight :: Int
    , CardWithUserFeatures -> Double
cardProficiencyScore :: Double
    , CardWithUserFeatures -> Bool
cardShouldDisplayHint :: Bool
    }

instance A.FromJSON DeckPreferences where
    parseJSON :: Value -> Parser DeckPreferences
parseJSON = Options -> Value -> Parser DeckPreferences
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
A.genericParseJSON Options
A.defaultOptions

instance A.FromJSON CardPreferences where
    parseJSON :: Value -> Parser CardPreferences
parseJSON = Options -> Value -> Parser CardPreferences
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
A.genericParseJSON Options
A.defaultOptions

instance A.FromJSON CardStatus where
    parseJSON :: Value -> Parser CardStatus
parseJSON = Options -> Value -> Parser CardStatus
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
A.genericParseJSON Options
A.defaultOptions

instance A.FromJSON DeckProficiency where
    parseJSON :: Value -> Parser DeckProficiency
parseJSON = Options -> Value -> Parser DeckProficiency
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
A.genericParseJSON Options
A.defaultOptions

instance A.FromJSON CardProficiency where
    parseJSON :: Value -> Parser CardProficiency
parseJSON = Options -> Value -> Parser CardProficiency
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
A.genericParseJSON Options
A.defaultOptions

instance A.ToJSON DeckPreferences where
    toEncoding :: DeckPreferences -> Encoding
toEncoding = Options -> DeckPreferences -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
A.genericToEncoding Options
A.defaultOptions

instance A.ToJSON CardPreferences where
    toEncoding :: CardPreferences -> Encoding
toEncoding = Options -> CardPreferences -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
A.genericToEncoding Options
A.defaultOptions

instance A.ToJSON CardStatus where
    toEncoding :: CardStatus -> Encoding
toEncoding = Options -> CardStatus -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
A.genericToEncoding Options
A.defaultOptions

instance A.ToJSON DeckProficiency where
    toEncoding :: DeckProficiency -> Encoding
toEncoding = Options -> DeckProficiency -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
A.genericToEncoding Options
A.defaultOptions

instance A.ToJSON CardProficiency where
    toEncoding :: CardProficiency -> Encoding
toEncoding = Options -> CardProficiency -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
A.genericToEncoding Options
A.defaultOptions