{-# 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.List
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text 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"
  Text -> GitLab [User]
forall a. FromJSON a => Text -> GitLab [a]
gitlabUnsafe 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
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
usrId)
  Either Status (Maybe User)
res <- Text -> GitLab (Either Status (Maybe User))
forall a. FromJSON a => Text -> GitLab (Either Status (Maybe a))
gitlabOne Text
path
  case Either Status (Maybe User)
res of
    Left Status
_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"
      attrs :: Text
attrs = Text
"&username=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
username
  [User]
res <- Text -> Text -> GitLab [User]
forall a. FromJSON a => Text -> Text -> GitLab [a]
gitlabWithAttrsUnsafe Text
path Text
attrs
  case [User]
res of
    [] -> Maybe User -> GitLab (Maybe User)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe User
forall a. Maybe a
Nothing
    (User
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 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))