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

-- |
-- Module      : Users
-- Description : Queries about registered users
-- Copyright   : (c) Rob Stewart, Heriot-Watt University, 2019
-- License     : BSD3
-- Maintainer  : robstewart57@gmail.com
-- Stability   : stable
module GitLab.API.Users where

import Data.Either
import Data.List
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import GitLab.Types
import GitLab.WebRequests.GitLabWebCalls

-- | all registered users.
allUsers :: GitLab [User]
allUsers :: GitLab [User]
allUsers = do
  let path :: Text
path = Text
"/users"
  [User] -> Either (Response ByteString) [User] -> [User]
forall b a. b -> Either a b -> b
fromRight ([Char] -> [User]
forall a. HasCallStack => [Char] -> a
error [Char]
"allUsers error") (Either (Response ByteString) [User] -> [User])
-> ReaderT GitLabState IO (Either (Response ByteString) [User])
-> GitLab [User]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> [GitLabParam]
-> ReaderT GitLabState IO (Either (Response ByteString) [User])
forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
path []

-- | searches for a user given a user ID. Returns @Just User@ if the
-- user is found, otherwise @Nothing@.
userId ::
  -- | username to search for
  Int ->
  GitLab (Maybe User)
userId :: Int -> GitLab (Maybe User)
userId Int
usrId = do
  let path :: Text
path =
        Text
"/users/"
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Char] -> Text
T.pack (Int -> [Char]
forall a. Show a => a -> [Char]
show Int
usrId)
  Either (Response ByteString) (Maybe User)
res <- Text
-> [GitLabParam]
-> GitLab (Either (Response ByteString) (Maybe User))
forall a.
FromJSON a =>
Text
-> [GitLabParam] -> GitLab (Either (Response ByteString) (Maybe a))
gitlabGetOne Text
path []
  case Either (Response ByteString) (Maybe User)
res of
    Left Response ByteString
_err -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe User
forall a. Maybe a
Nothing
    Right Maybe User
Nothing -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe User
forall a. Maybe a
Nothing
    Right (Just User
user) -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return (User -> Maybe User
forall a. a -> Maybe a
Just User
user)

-- | searches for a user given a username. Returns @Just User@ if the
-- user is found, otherwise @Nothing@.
searchUser ::
  -- | username to search for
  Text ->
  GitLab (Maybe User)
searchUser :: Text -> GitLab (Maybe User)
searchUser Text
username = do
  let path :: Text
path = Text
"/users"
      params :: [GitLabParam]
params = [(ByteString
"username", ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (Text -> ByteString
T.encodeUtf8 Text
username))]
  Either (Response ByteString) [User]
result <- Text
-> [GitLabParam]
-> ReaderT GitLabState IO (Either (Response ByteString) [User])
forall a.
FromJSON a =>
Text -> [GitLabParam] -> GitLab (Either (Response ByteString) [a])
gitlabGetMany Text
path [GitLabParam]
params
  case Either (Response ByteString) [User]
result of
    Left Response ByteString
_err -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe User
forall a. Maybe a
Nothing
    Right [] -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe User
forall a. Maybe a
Nothing
    Right (User
x : [User]
_) -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return (User -> Maybe User
forall a. a -> Maybe a
Just User
x)

-- | searches for users given a list of usernames, returns them in
-- alphabetical order of their usernames.
orderedUsers ::
  -- | usernames to search for
  [Text] ->
  GitLab [User]
orderedUsers :: [Text] -> GitLab [User]
orderedUsers [Text]
usernames = do
  [User]
users <- [Maybe User] -> [User]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe User] -> [User])
-> ReaderT GitLabState IO [Maybe User] -> GitLab [User]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Text -> GitLab (Maybe User))
-> [Text] -> ReaderT GitLabState IO [Maybe User]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Text -> GitLab (Maybe User)
searchUser [Text]
usernames
  [User] -> GitLab [User]
forall (m :: * -> *) a. Monad m => a -> m a
return ([User] -> [User]
orderUsersByName [User]
users)
  where
    orderUsersByName :: [User] -> [User]
    orderUsersByName :: [User] -> [User]
orderUsersByName =
      (User -> User -> Ordering) -> [User] -> [User]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (\User
u1 User
u2 -> Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (User -> Text
user_name User
u1) (User -> Text
user_name User
u2))