{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}

module Gerrit.Data.Account
  ( GerritAccountId (..),
    GerritAccount (..),
    GerritAccountQuery (..),
    userQueryText,
    accountQs,
  )
where

import Control.Monad (mzero)
import Data.Aeson
import Data.List.NonEmpty (NonEmpty, toList)
import Data.Text (Text)
import qualified Data.Text as T

-- https://gerrit-review.googlesource.com/Documentation/user-search-accounts.html#_search_operators
data GerritAccountQuery
  = CanSee Text
  | Email Text
  | Name Text
  | Username Text
  | IsActive
  | IsInactive

userQueryText :: GerritAccountQuery -> Text
userQueryText :: GerritAccountQuery -> Text
userQueryText GerritAccountQuery
guq = case GerritAccountQuery
guq of
  CanSee Text
change -> Text
"cansee:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
change
  Email Text
email -> Text
"email:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
email
  Name Text
name -> Text
"name:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
escapeChar Text
name
  Username Text
username -> Text
"username:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
username
  GerritAccountQuery
IsActive -> Text
"is:active"
  GerritAccountQuery
IsInactive -> Text
"is:inactive"
  where
    escapeChar :: Text -> Text
escapeChar = Text -> Text -> Text -> Text
T.replace Text
"'" Text
" "

accountQs :: Int -> NonEmpty GerritAccountQuery -> Text
accountQs :: Int -> NonEmpty GerritAccountQuery -> Text
accountQs Int
count NonEmpty GerritAccountQuery
queries = Text -> [Text] -> Text
T.intercalate Text
"&" [Text
searchString, Text
countString]
  where
    searchString :: Text
searchString = Text
"q=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
"+" ((GerritAccountQuery -> Text) -> [GerritAccountQuery] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map GerritAccountQuery -> Text
userQueryText ([GerritAccountQuery] -> [Text]) -> [GerritAccountQuery] -> [Text]
forall a b. (a -> b) -> a -> b
$ NonEmpty GerritAccountQuery -> [GerritAccountQuery]
forall a. NonEmpty a -> [a]
toList NonEmpty GerritAccountQuery
queries)
    countString :: Text
countString = Text
"n=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
count)

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

instance FromJSON GerritAccountId where
  parseJSON :: Value -> Parser GerritAccountId
parseJSON (Object Object
v) = Int -> Maybe Bool -> GerritAccountId
GerritAccountId (Int -> Maybe Bool -> GerritAccountId)
-> Parser Int -> Parser (Maybe Bool -> GerritAccountId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Text -> Parser Int
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"_account_id" Parser (Maybe Bool -> GerritAccountId)
-> Parser (Maybe Bool) -> Parser GerritAccountId
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"_more_accounts"
  parseJSON Value
_ = Parser GerritAccountId
forall (m :: * -> *) a. MonadPlus m => m a
mzero

data GerritAccount = GerritAccount
  { GerritAccount -> Int
gerritAccountId :: Int,
    GerritAccount -> Text
gerritAccountName :: Text,
    GerritAccount -> Maybe Text
gerritAccountUsername :: Maybe Text,
    GerritAccount -> Maybe Text
gerritAccountEmail :: Maybe Text,
    GerritAccount -> Maybe Bool
gerritAccountHasMore :: Maybe Bool
  }
  deriving (GerritAccount -> GerritAccount -> Bool
(GerritAccount -> GerritAccount -> Bool)
-> (GerritAccount -> GerritAccount -> Bool) -> Eq GerritAccount
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GerritAccount -> GerritAccount -> Bool
$c/= :: GerritAccount -> GerritAccount -> Bool
== :: GerritAccount -> GerritAccount -> Bool
$c== :: GerritAccount -> GerritAccount -> Bool
Eq, Int -> GerritAccount -> ShowS
[GerritAccount] -> ShowS
GerritAccount -> String
(Int -> GerritAccount -> ShowS)
-> (GerritAccount -> String)
-> ([GerritAccount] -> ShowS)
-> Show GerritAccount
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GerritAccount] -> ShowS
$cshowList :: [GerritAccount] -> ShowS
show :: GerritAccount -> String
$cshow :: GerritAccount -> String
showsPrec :: Int -> GerritAccount -> ShowS
$cshowsPrec :: Int -> GerritAccount -> ShowS
Show)

instance FromJSON GerritAccount where
  parseJSON :: Value -> Parser GerritAccount
parseJSON (Object Object
v) =
    Int
-> Text -> Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount
GerritAccount
      (Int
 -> Text -> Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount)
-> Parser Int
-> Parser
     (Text -> Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Text -> Parser Int
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"_account_id"
      Parser
  (Text -> Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount)
-> Parser Text
-> Parser (Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser Text
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"name"
      Parser (Maybe Text -> Maybe Text -> Maybe Bool -> GerritAccount)
-> Parser (Maybe Text)
-> Parser (Maybe Text -> Maybe Bool -> GerritAccount)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"username"
      Parser (Maybe Text -> Maybe Bool -> GerritAccount)
-> Parser (Maybe Text) -> Parser (Maybe Bool -> GerritAccount)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Text)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"email"
      Parser (Maybe Bool -> GerritAccount)
-> Parser (Maybe Bool) -> Parser GerritAccount
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Text -> Parser (Maybe Bool)
forall a. FromJSON a => Object -> Text -> Parser (Maybe a)
.:? Text
"_more_accounts"
  parseJSON Value
_ = Parser GerritAccount
forall (m :: * -> *) a. MonadPlus m => m a
mzero