{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

module Poseidon.ServerClient (
    ServerApiReturnType(..),
    ApiReturnData(..),
    processApiResponse,
    ArchiveEndpoint(..),
    PackageInfo (..), GroupInfo (..), ExtendedIndividualInfo(..),
    extIndInfo2IndInfoCollection,
    qDefault, qArchive, qPacVersion, (+&+),
    AddJannoColSpec(..)
) where

import           Paths_poseidon_hs      (version)
import           Poseidon.EntityTypes   (HasNameAndVersion (..),
                                         IndividualInfo (..),
                                         IndividualInfoCollection,
                                         PacNameAndVersion (..))
import           Poseidon.Janno         (JannoRows)
import           Poseidon.Utils         (PoseidonException (..), PoseidonIO,
                                         logError, logInfo)

import           Control.Exception      (catch, throwIO)
import           Control.Monad          (forM_, unless)
import           Control.Monad.IO.Class (liftIO)
import           Data.Aeson             (FromJSON, ToJSON (..), Value (String),
                                         eitherDecode', object, parseJSON,
                                         toJSON, withObject, (.:), (.=))
import           Data.Time              (Day)
import           Data.Version           (Version, showVersion)
import           GHC.Generics           (Generic)
import           Network.HTTP.Conduit   (simpleHttp)

--  Client Server Communication types and functions

qDefault :: Maybe String -> String
qDefault :: Maybe [Char] -> [Char]
qDefault Maybe [Char]
archive = [Char]
qVersion [Char] -> [Char] -> [Char]
+&+ Maybe [Char] -> [Char]
qArchive Maybe [Char]
archive

(+&+) :: String -> String -> String
+&+ :: [Char] -> [Char] -> [Char]
(+&+) [Char]
a (Char
'?':[Char]
b) = [Char]
a [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"&" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
b
(+&+) [Char]
a [Char]
b       = [Char]
a [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"&" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
b

qPacVersion :: Maybe Version -> String
qPacVersion :: Maybe Version -> [Char]
qPacVersion Maybe Version
Nothing  = [Char]
""
qPacVersion (Just Version
v) = [Char]
"?package_version=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Version -> [Char]
showVersion Version
v

qVersion :: String
qVersion :: [Char]
qVersion = [Char]
"?client_version=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Version -> [Char]
showVersion Version
version

qArchive :: Maybe String -> String
qArchive :: Maybe [Char] -> [Char]
qArchive Maybe [Char]
Nothing     = [Char]
""
qArchive (Just [Char]
name) = [Char]
"?archive=" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
name

data ArchiveEndpoint = ArchiveEndpoint {
      ArchiveEndpoint -> [Char]
_aeServerURL   :: String
    , ArchiveEndpoint -> Maybe [Char]
_aeArchiveName :: Maybe String
}

data ServerApiReturnType = ServerApiReturnType {
    ServerApiReturnType -> [[Char]]
_apiMessages :: [String],
    ServerApiReturnType -> Maybe ApiReturnData
_apiResponse :: Maybe ApiReturnData
}

instance ToJSON ServerApiReturnType where
    toJSON :: ServerApiReturnType -> Value
toJSON (ServerApiReturnType [[Char]]
messages Maybe ApiReturnData
response) =
        [Pair] -> Value
object [
            Key
"serverMessages" Key -> [[Char]] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [[Char]]
messages,
            Key
"serverResponse" Key -> Maybe ApiReturnData -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe ApiReturnData
response
        ]

instance FromJSON ServerApiReturnType where
    parseJSON :: Value -> Parser ServerApiReturnType
parseJSON = [Char]
-> (Object -> Parser ServerApiReturnType)
-> Value
-> Parser ServerApiReturnType
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"ServerApiReturnType" ((Object -> Parser ServerApiReturnType)
 -> Value -> Parser ServerApiReturnType)
-> (Object -> Parser ServerApiReturnType)
-> Value
-> Parser ServerApiReturnType
forall a b. (a -> b) -> a -> b
$ \Object
v -> [[Char]] -> Maybe ApiReturnData -> ServerApiReturnType
ServerApiReturnType
            ([[Char]] -> Maybe ApiReturnData -> ServerApiReturnType)
-> Parser [[Char]]
-> Parser (Maybe ApiReturnData -> ServerApiReturnType)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"serverMessages"
            Parser (Maybe ApiReturnData -> ServerApiReturnType)
-> Parser (Maybe ApiReturnData) -> Parser ServerApiReturnType
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe ApiReturnData)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"serverResponse"

data ApiReturnData = ApiReturnPackageInfo [PackageInfo]
                   | ApiReturnGroupInfo [GroupInfo]
                   | ApiReturnExtIndividualInfo [ExtendedIndividualInfo]
                   | ApiReturnJanno [(String, JannoRows)] deriving ((forall x. ApiReturnData -> Rep ApiReturnData x)
-> (forall x. Rep ApiReturnData x -> ApiReturnData)
-> Generic ApiReturnData
forall x. Rep ApiReturnData x -> ApiReturnData
forall x. ApiReturnData -> Rep ApiReturnData x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ApiReturnData -> Rep ApiReturnData x
from :: forall x. ApiReturnData -> Rep ApiReturnData x
$cto :: forall x. Rep ApiReturnData x -> ApiReturnData
to :: forall x. Rep ApiReturnData x -> ApiReturnData
Generic)

instance ToJSON ApiReturnData where
    toJSON :: ApiReturnData -> Value
toJSON (ApiReturnPackageInfo [PackageInfo]
pacInfo) =
        [Pair] -> Value
object [
            Key
"constructor" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text -> Value
String Text
"ApiReturnPackageInfo",
            Key
"packageInfo" Key -> [PackageInfo] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [PackageInfo]
pacInfo
        ]
    toJSON (ApiReturnGroupInfo [GroupInfo]
groupInfo) =
        [Pair] -> Value
object [
            Key
"constructor" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text -> Value
String Text
"ApiReturnGroupInfo",
            Key
"groupInfo" Key -> [GroupInfo] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [GroupInfo]
groupInfo
        ]
    toJSON (ApiReturnExtIndividualInfo [ExtendedIndividualInfo]
indInfo) =
        [Pair] -> Value
object [
            Key
"constructor" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text -> Value
String Text
"ApiReturnExtIndividualInfo",
            Key
"extIndInfo" Key -> [ExtendedIndividualInfo] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [ExtendedIndividualInfo]
indInfo
        ]
    toJSON (ApiReturnJanno [([Char], JannoRows)]
janno) =
        [Pair] -> Value
object [
            Key
"constructor" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Text -> Value
String Text
"ApiReturnJanno",
            Key
"janno" Key -> [([Char], JannoRows)] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [([Char], JannoRows)]
janno
        ]

instance FromJSON ApiReturnData where
    parseJSON :: Value -> Parser ApiReturnData
parseJSON = [Char]
-> (Object -> Parser ApiReturnData)
-> Value
-> Parser ApiReturnData
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"ApiReturnData" ((Object -> Parser ApiReturnData) -> Value -> Parser ApiReturnData)
-> (Object -> Parser ApiReturnData)
-> Value
-> Parser ApiReturnData
forall a b. (a -> b) -> a -> b
$ \Object
v -> do
        [Char]
constr <- Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"constructor"
        case [Char]
constr of
            [Char]
"ApiReturnPackageInfo"       -> [PackageInfo] -> ApiReturnData
ApiReturnPackageInfo       ([PackageInfo] -> ApiReturnData)
-> Parser [PackageInfo] -> Parser ApiReturnData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [PackageInfo]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageInfo"
            [Char]
"ApiReturnGroupInfo"         -> [GroupInfo] -> ApiReturnData
ApiReturnGroupInfo         ([GroupInfo] -> ApiReturnData)
-> Parser [GroupInfo] -> Parser ApiReturnData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [GroupInfo]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"groupInfo"
            [Char]
"ApiReturnExtIndividualInfo" -> [ExtendedIndividualInfo] -> ApiReturnData
ApiReturnExtIndividualInfo ([ExtendedIndividualInfo] -> ApiReturnData)
-> Parser [ExtendedIndividualInfo] -> Parser ApiReturnData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [ExtendedIndividualInfo]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"extIndInfo"
            [Char]
"ApiReturnJanno"             -> [([Char], JannoRows)] -> ApiReturnData
ApiReturnJanno             ([([Char], JannoRows)] -> ApiReturnData)
-> Parser [([Char], JannoRows)] -> Parser ApiReturnData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [([Char], JannoRows)]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"janno"
            [Char]
_                            -> [Char] -> Parser ApiReturnData
forall a. HasCallStack => [Char] -> a
error ([Char] -> Parser ApiReturnData) -> [Char] -> Parser ApiReturnData
forall a b. (a -> b) -> a -> b
$ [Char]
"cannot parse ApiReturnType with constructor " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
constr


data PackageInfo = PackageInfo
    { PackageInfo -> PacNameAndVersion
pPac           :: PacNameAndVersion
    , PackageInfo -> Bool
pIsLatest      :: Bool
    , PackageInfo -> Version
pPosVersion    :: Version
    , PackageInfo -> Maybe [Char]
pDescription   :: Maybe String
    , PackageInfo -> Maybe Day
pLastModified  :: Maybe Day
    , PackageInfo -> Int
pNrIndividuals :: Int
    } deriving (PackageInfo -> PackageInfo -> Bool
(PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> Bool) -> Eq PackageInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PackageInfo -> PackageInfo -> Bool
== :: PackageInfo -> PackageInfo -> Bool
$c/= :: PackageInfo -> PackageInfo -> Bool
/= :: PackageInfo -> PackageInfo -> Bool
Eq, Eq PackageInfo
Eq PackageInfo
-> (PackageInfo -> PackageInfo -> Ordering)
-> (PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> Bool)
-> (PackageInfo -> PackageInfo -> PackageInfo)
-> (PackageInfo -> PackageInfo -> PackageInfo)
-> Ord PackageInfo
PackageInfo -> PackageInfo -> Bool
PackageInfo -> PackageInfo -> Ordering
PackageInfo -> PackageInfo -> PackageInfo
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PackageInfo -> PackageInfo -> Ordering
compare :: PackageInfo -> PackageInfo -> Ordering
$c< :: PackageInfo -> PackageInfo -> Bool
< :: PackageInfo -> PackageInfo -> Bool
$c<= :: PackageInfo -> PackageInfo -> Bool
<= :: PackageInfo -> PackageInfo -> Bool
$c> :: PackageInfo -> PackageInfo -> Bool
> :: PackageInfo -> PackageInfo -> Bool
$c>= :: PackageInfo -> PackageInfo -> Bool
>= :: PackageInfo -> PackageInfo -> Bool
$cmax :: PackageInfo -> PackageInfo -> PackageInfo
max :: PackageInfo -> PackageInfo -> PackageInfo
$cmin :: PackageInfo -> PackageInfo -> PackageInfo
min :: PackageInfo -> PackageInfo -> PackageInfo
Ord)

instance HasNameAndVersion PackageInfo where
    getPacName :: PackageInfo -> [Char]
getPacName = PacNameAndVersion -> [Char]
forall a. HasNameAndVersion a => a -> [Char]
getPacName (PacNameAndVersion -> [Char])
-> (PackageInfo -> PacNameAndVersion) -> PackageInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageInfo -> PacNameAndVersion
pPac
    getPacVersion :: PackageInfo -> Maybe Version
getPacVersion = PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion (PacNameAndVersion -> Maybe Version)
-> (PackageInfo -> PacNameAndVersion)
-> PackageInfo
-> Maybe Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageInfo -> PacNameAndVersion
pPac

instance ToJSON PackageInfo where
    toJSON :: PackageInfo -> Value
toJSON (PackageInfo (PacNameAndVersion [Char]
n Maybe Version
v) Bool
isLatest Version
posVersion Maybe [Char]
description Maybe Day
lastModified Int
nrIndividuals) =
        [Pair] -> Value
object [
            Key
"packageTitle"    Key -> [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [Char]
n,
            Key
"packageVersion"  Key -> Maybe Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe Version
v,
            Key
"isLatest" Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Bool
isLatest,
            Key
"poseidonVersion" Key -> Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Version
posVersion,
            Key
"description"     Key -> Maybe [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe [Char]
description,
            Key
"lastModified"    Key -> Maybe Day -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe Day
lastModified,
            Key
"nrIndividuals"   Key -> Int -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Int
nrIndividuals
        ]

instance FromJSON PackageInfo where
    parseJSON :: Value -> Parser PackageInfo
parseJSON = [Char]
-> (Object -> Parser PackageInfo) -> Value -> Parser PackageInfo
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"PackageInfo" ((Object -> Parser PackageInfo) -> Value -> Parser PackageInfo)
-> (Object -> Parser PackageInfo) -> Value -> Parser PackageInfo
forall a b. (a -> b) -> a -> b
$ \Object
v -> PacNameAndVersion
-> Bool
-> Version
-> Maybe [Char]
-> Maybe Day
-> Int
-> PackageInfo
PackageInfo
            (PacNameAndVersion
 -> Bool
 -> Version
 -> Maybe [Char]
 -> Maybe Day
 -> Int
 -> PackageInfo)
-> Parser PacNameAndVersion
-> Parser
     (Bool
      -> Version -> Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Char] -> Maybe Version -> PacNameAndVersion
PacNameAndVersion ([Char] -> Maybe Version -> PacNameAndVersion)
-> Parser [Char] -> Parser (Maybe Version -> PacNameAndVersion)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageTitle") Parser (Maybe Version -> PacNameAndVersion)
-> Parser (Maybe Version) -> Parser PacNameAndVersion
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Object
v Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageVersion"))
            Parser
  (Bool
   -> Version -> Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
-> Parser Bool
-> Parser
     (Version -> Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Bool
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"isLatest"
            Parser (Version -> Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
-> Parser Version
-> Parser (Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Version
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"poseidonVersion"
            Parser (Maybe [Char] -> Maybe Day -> Int -> PackageInfo)
-> Parser (Maybe [Char])
-> Parser (Maybe Day -> Int -> PackageInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe [Char])
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"description"
            Parser (Maybe Day -> Int -> PackageInfo)
-> Parser (Maybe Day) -> Parser (Int -> PackageInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe Day)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"lastModified"
            Parser (Int -> PackageInfo) -> Parser Int -> Parser PackageInfo
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"nrIndividuals"

data GroupInfo = GroupInfo
    { GroupInfo -> [Char]
gName          :: String
    , GroupInfo -> PacNameAndVersion
gPackage       :: PacNameAndVersion
    , GroupInfo -> Bool
gIsLatest      :: Bool
    , GroupInfo -> Int
gNrIndividuals :: Int
    } deriving (GroupInfo -> GroupInfo -> Bool
(GroupInfo -> GroupInfo -> Bool)
-> (GroupInfo -> GroupInfo -> Bool) -> Eq GroupInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GroupInfo -> GroupInfo -> Bool
== :: GroupInfo -> GroupInfo -> Bool
$c/= :: GroupInfo -> GroupInfo -> Bool
/= :: GroupInfo -> GroupInfo -> Bool
Eq)

instance ToJSON GroupInfo where
    toJSON :: GroupInfo -> Value
toJSON (GroupInfo [Char]
name (PacNameAndVersion [Char]
pacTitle Maybe Version
pacVersion) Bool
isLatest Int
nrIndividuals) =
        [Pair] -> Value
object [
            Key
"groupName"       Key -> [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [Char]
name,
            Key
"packageTitle"    Key -> [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= [Char]
pacTitle,
            Key
"packageVersion"  Key -> Maybe Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Maybe Version
pacVersion,
            Key
"isLatest" Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Bool
isLatest,
            Key
"nrIndividuals"   Key -> Int -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= Int
nrIndividuals
        ]

instance FromJSON GroupInfo where
    parseJSON :: Value -> Parser GroupInfo
parseJSON = [Char] -> (Object -> Parser GroupInfo) -> Value -> Parser GroupInfo
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"GroupInfo" ((Object -> Parser GroupInfo) -> Value -> Parser GroupInfo)
-> (Object -> Parser GroupInfo) -> Value -> Parser GroupInfo
forall a b. (a -> b) -> a -> b
$ \Object
v -> do
        [Char]
groupName      <- Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"groupName"
        [Char]
packageTitle   <- Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageTitle"
        Maybe Version
packageVersion <- Object
v Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageVersion"
        Bool
isLatest       <- Object
v Object -> Key -> Parser Bool
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"isLatest"
        Int
nrIndividuals  <- Object
v Object -> Key -> Parser Int
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"nrIndividuals"
        GroupInfo -> Parser GroupInfo
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (GroupInfo -> Parser GroupInfo) -> GroupInfo -> Parser GroupInfo
forall a b. (a -> b) -> a -> b
$ [Char] -> PacNameAndVersion -> Bool -> Int -> GroupInfo
GroupInfo [Char]
groupName ([Char] -> Maybe Version -> PacNameAndVersion
PacNameAndVersion [Char]
packageTitle Maybe Version
packageVersion) Bool
isLatest Int
nrIndividuals

instance HasNameAndVersion GroupInfo where
    getPacName :: GroupInfo -> [Char]
getPacName = PacNameAndVersion -> [Char]
forall a. HasNameAndVersion a => a -> [Char]
getPacName (PacNameAndVersion -> [Char])
-> (GroupInfo -> PacNameAndVersion) -> GroupInfo -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GroupInfo -> PacNameAndVersion
gPackage
    getPacVersion :: GroupInfo -> Maybe Version
getPacVersion = PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion (PacNameAndVersion -> Maybe Version)
-> (GroupInfo -> PacNameAndVersion) -> GroupInfo -> Maybe Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GroupInfo -> PacNameAndVersion
gPackage

data ExtendedIndividualInfo = ExtendedIndividualInfo
    {
      ExtendedIndividualInfo -> [Char]
extIndInfoName     :: String
    , ExtendedIndividualInfo -> [[Char]]
extIndInfoGroups   :: [String]
    , ExtendedIndividualInfo -> PacNameAndVersion
extIndInfoPac      :: PacNameAndVersion
    , ExtendedIndividualInfo -> Bool
extIndInfoIsLatest :: Bool
    , ExtendedIndividualInfo -> [([Char], Maybe [Char])]
extIndInfoAddCols  :: [(String, Maybe String)]
    } deriving (ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool
(ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool)
-> (ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool)
-> Eq ExtendedIndividualInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool
== :: ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool
$c/= :: ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool
/= :: ExtendedIndividualInfo -> ExtendedIndividualInfo -> Bool
Eq)

instance HasNameAndVersion ExtendedIndividualInfo where
    getPacName :: ExtendedIndividualInfo -> [Char]
getPacName = PacNameAndVersion -> [Char]
forall a. HasNameAndVersion a => a -> [Char]
getPacName (PacNameAndVersion -> [Char])
-> (ExtendedIndividualInfo -> PacNameAndVersion)
-> ExtendedIndividualInfo
-> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> PacNameAndVersion
extIndInfoPac
    getPacVersion :: ExtendedIndividualInfo -> Maybe Version
getPacVersion = PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion (PacNameAndVersion -> Maybe Version)
-> (ExtendedIndividualInfo -> PacNameAndVersion)
-> ExtendedIndividualInfo
-> Maybe Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> PacNameAndVersion
extIndInfoPac

instance ToJSON ExtendedIndividualInfo where
    toJSON :: ExtendedIndividualInfo -> Value
toJSON ExtendedIndividualInfo
e =
        [Pair] -> Value
object [
            Key
"poseidonID"             Key -> [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= ExtendedIndividualInfo -> [Char]
extIndInfoName ExtendedIndividualInfo
e,
            Key
"groupNames"             Key -> [[Char]] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= ExtendedIndividualInfo -> [[Char]]
extIndInfoGroups ExtendedIndividualInfo
e,
            Key
"packageTitle"           Key -> [Char] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (PacNameAndVersion -> [Char]
forall a. HasNameAndVersion a => a -> [Char]
getPacName     (PacNameAndVersion -> [Char])
-> (ExtendedIndividualInfo -> PacNameAndVersion)
-> ExtendedIndividualInfo
-> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> PacNameAndVersion
extIndInfoPac (ExtendedIndividualInfo -> [Char])
-> ExtendedIndividualInfo -> [Char]
forall a b. (a -> b) -> a -> b
$ ExtendedIndividualInfo
e),
            Key
"packageVersion"         Key -> Maybe Version -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= (PacNameAndVersion -> Maybe Version
forall a. HasNameAndVersion a => a -> Maybe Version
getPacVersion  (PacNameAndVersion -> Maybe Version)
-> (ExtendedIndividualInfo -> PacNameAndVersion)
-> ExtendedIndividualInfo
-> Maybe Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExtendedIndividualInfo -> PacNameAndVersion
extIndInfoPac (ExtendedIndividualInfo -> Maybe Version)
-> ExtendedIndividualInfo -> Maybe Version
forall a b. (a -> b) -> a -> b
$ ExtendedIndividualInfo
e),
            Key
"isLatest"               Key -> Bool -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= ExtendedIndividualInfo -> Bool
extIndInfoIsLatest ExtendedIndividualInfo
e,
            Key
"additionalJannoColumns" Key -> [([Char], Maybe [Char])] -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
.= ExtendedIndividualInfo -> [([Char], Maybe [Char])]
extIndInfoAddCols ExtendedIndividualInfo
e]

instance FromJSON ExtendedIndividualInfo where
    parseJSON :: Value -> Parser ExtendedIndividualInfo
parseJSON = [Char]
-> (Object -> Parser ExtendedIndividualInfo)
-> Value
-> Parser ExtendedIndividualInfo
forall a. [Char] -> (Object -> Parser a) -> Value -> Parser a
withObject [Char]
"ExtendedIndividualInfo" ((Object -> Parser ExtendedIndividualInfo)
 -> Value -> Parser ExtendedIndividualInfo)
-> (Object -> Parser ExtendedIndividualInfo)
-> Value
-> Parser ExtendedIndividualInfo
forall a b. (a -> b) -> a -> b
$ \Object
v -> [Char]
-> [[Char]]
-> PacNameAndVersion
-> Bool
-> [([Char], Maybe [Char])]
-> ExtendedIndividualInfo
ExtendedIndividualInfo
            ([Char]
 -> [[Char]]
 -> PacNameAndVersion
 -> Bool
 -> [([Char], Maybe [Char])]
 -> ExtendedIndividualInfo)
-> Parser [Char]
-> Parser
     ([[Char]]
      -> PacNameAndVersion
      -> Bool
      -> [([Char], Maybe [Char])]
      -> ExtendedIndividualInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"poseidonID"
            Parser
  ([[Char]]
   -> PacNameAndVersion
   -> Bool
   -> [([Char], Maybe [Char])]
   -> ExtendedIndividualInfo)
-> Parser [[Char]]
-> Parser
     (PacNameAndVersion
      -> Bool -> [([Char], Maybe [Char])] -> ExtendedIndividualInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser [[Char]]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"groupNames"
            Parser
  (PacNameAndVersion
   -> Bool -> [([Char], Maybe [Char])] -> ExtendedIndividualInfo)
-> Parser PacNameAndVersion
-> Parser
     (Bool -> [([Char], Maybe [Char])] -> ExtendedIndividualInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ([Char] -> Maybe Version -> PacNameAndVersion
PacNameAndVersion ([Char] -> Maybe Version -> PacNameAndVersion)
-> Parser [Char] -> Parser (Maybe Version -> PacNameAndVersion)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
v Object -> Key -> Parser [Char]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageTitle") Parser (Maybe Version -> PacNameAndVersion)
-> Parser (Maybe Version) -> Parser PacNameAndVersion
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Object
v Object -> Key -> Parser (Maybe Version)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"packageVersion"))
            Parser (Bool -> [([Char], Maybe [Char])] -> ExtendedIndividualInfo)
-> Parser Bool
-> Parser ([([Char], Maybe [Char])] -> ExtendedIndividualInfo)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Bool
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"isLatest"
            Parser ([([Char], Maybe [Char])] -> ExtendedIndividualInfo)
-> Parser [([Char], Maybe [Char])] -> Parser ExtendedIndividualInfo
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser [([Char], Maybe [Char])]
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"additionalJannoColumns"

processApiResponse :: String -> Bool -> PoseidonIO ApiReturnData
processApiResponse :: [Char] -> Bool -> PoseidonIO ApiReturnData
processApiResponse [Char]
url Bool
quiet = do
    ByteString
remoteData <- IO ByteString -> ReaderT Env IO ByteString
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> ReaderT Env IO ByteString)
-> IO ByteString -> ReaderT Env IO ByteString
forall a b. (a -> b) -> a -> b
$ IO ByteString -> (HttpException -> IO ByteString) -> IO ByteString
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch ([Char] -> IO ByteString
forall (m :: * -> *). MonadIO m => [Char] -> m ByteString
simpleHttp [Char]
url) (PoseidonException -> IO ByteString
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO ByteString)
-> (HttpException -> PoseidonException)
-> HttpException
-> IO ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HttpException -> PoseidonException
PoseidonHttpExceptionForward)
    ServerApiReturnType [[Char]]
messages Maybe ApiReturnData
maybeReturn <- case ByteString -> Either [Char] ServerApiReturnType
forall a. FromJSON a => ByteString -> Either [Char] a
eitherDecode' ByteString
remoteData of
        Left [Char]
err  -> IO ServerApiReturnType -> ReaderT Env IO ServerApiReturnType
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ServerApiReturnType -> ReaderT Env IO ServerApiReturnType)
-> (PoseidonException -> IO ServerApiReturnType)
-> PoseidonException
-> ReaderT Env IO ServerApiReturnType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO ServerApiReturnType
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> ReaderT Env IO ServerApiReturnType)
-> PoseidonException -> ReaderT Env IO ServerApiReturnType
forall a b. (a -> b) -> a -> b
$ [Char] -> PoseidonException
PoseidonRemoteJSONParsingException [Char]
err
        Right ServerApiReturnType
sam -> ServerApiReturnType -> ReaderT Env IO ServerApiReturnType
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ServerApiReturnType
sam
    Bool -> ReaderT Env IO () -> ReaderT Env IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([[Char]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Char]]
messages Bool -> Bool -> Bool
|| Bool
quiet) (ReaderT Env IO () -> ReaderT Env IO ())
-> ReaderT Env IO () -> ReaderT Env IO ()
forall a b. (a -> b) -> a -> b
$
        [[Char]] -> ([Char] -> ReaderT Env IO ()) -> ReaderT Env IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [[Char]]
messages (\[Char]
msg -> [Char] -> ReaderT Env IO ()
logInfo ([Char] -> ReaderT Env IO ()) -> [Char] -> ReaderT Env IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Message from the Server: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
msg)
    case Maybe ApiReturnData
maybeReturn of
        Just ApiReturnData
apiReturn -> ApiReturnData -> PoseidonIO ApiReturnData
forall a. a -> ReaderT Env IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ApiReturnData
apiReturn
        Maybe ApiReturnData
Nothing -> do
            [Char] -> ReaderT Env IO ()
logError [Char]
"The server request was unsuccessful"
            IO ApiReturnData -> PoseidonIO ApiReturnData
forall a. IO a -> ReaderT Env IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ApiReturnData -> PoseidonIO ApiReturnData)
-> ([Char] -> IO ApiReturnData)
-> [Char]
-> PoseidonIO ApiReturnData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PoseidonException -> IO ApiReturnData
forall e a. Exception e => e -> IO a
throwIO (PoseidonException -> IO ApiReturnData)
-> ([Char] -> PoseidonException) -> [Char] -> IO ApiReturnData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> PoseidonException
PoseidonServerCommunicationException ([Char] -> PoseidonIO ApiReturnData)
-> [Char] -> PoseidonIO ApiReturnData
forall a b. (a -> b) -> a -> b
$ [Char]
"Server error upon URL " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
url

extIndInfo2IndInfoCollection :: [ExtendedIndividualInfo] -> IndividualInfoCollection
extIndInfo2IndInfoCollection :: [ExtendedIndividualInfo] -> IndividualInfoCollection
extIndInfo2IndInfoCollection [ExtendedIndividualInfo]
extIndInfos =
    let indInfos :: [IndividualInfo]
indInfos  = [[Char] -> [[Char]] -> PacNameAndVersion -> IndividualInfo
IndividualInfo [Char]
n [[Char]]
g PacNameAndVersion
p | ExtendedIndividualInfo [Char]
n [[Char]]
g PacNameAndVersion
p Bool
_ [([Char], Maybe [Char])]
_ <- [ExtendedIndividualInfo]
extIndInfos]
        areLatest :: [Bool]
areLatest = (ExtendedIndividualInfo -> Bool)
-> [ExtendedIndividualInfo] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map ExtendedIndividualInfo -> Bool
extIndInfoIsLatest [ExtendedIndividualInfo]
extIndInfos
    in  ([IndividualInfo]
indInfos, [Bool]
areLatest)

-- type needed to specify additional Janno Columns to be queried from packages
data AddJannoColSpec = AddJannoColList [String] | AddJannoColAll