-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Wire.API.Routes.MultiTablePaging
  ( GetMultiTablePageRequest (..),
    MultiTablePage (..),
    LocalOrRemoteTable (..),
    MultiTablePagingState (..),
  )
where

import Control.Lens ((?~))
import Data.Aeson (FromJSON (..), ToJSON (..))
import Data.Kind
import Data.OpenApi qualified as S
import Data.Proxy
import Data.Range
import Data.Schema
import Data.Text qualified as Text
import GHC.TypeLits
import Imports
import Wire.API.Routes.MultiTablePaging.State

-- | A request for a page of results from the database. Type arguments:
--
--  * @name@   Name of the resources being paginated through
--  * @tables@ A (usually finite) type that represent the table currently being
--             used (must be an instance of 'PagingTable')
--  * @max@    Maximum page size
--  * @def@    Default page size
--
-- See 'ConversationPagingState' for an example.
data GetMultiTablePageRequest (name :: Symbol) (tables :: Type) (max :: Nat) (def :: Nat) = GetMultiTablePageRequest
  { forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
GetMultiTablePageRequest name tables max def -> Range 1 max Int32
gmtprSize :: Range 1 max Int32,
    forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
GetMultiTablePageRequest name tables max def
-> Maybe (MultiTablePagingState name tables)
gmtprState :: Maybe (MultiTablePagingState name tables)
  }
  deriving stock (Int -> GetMultiTablePageRequest name tables max def -> ShowS
[GetMultiTablePageRequest name tables max def] -> ShowS
GetMultiTablePageRequest name tables max def -> String
(Int -> GetMultiTablePageRequest name tables max def -> ShowS)
-> (GetMultiTablePageRequest name tables max def -> String)
-> ([GetMultiTablePageRequest name tables max def] -> ShowS)
-> Show (GetMultiTablePageRequest name tables max def)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
Int -> GetMultiTablePageRequest name tables max def -> ShowS
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
[GetMultiTablePageRequest name tables max def] -> ShowS
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
GetMultiTablePageRequest name tables max def -> String
$cshowsPrec :: forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
Int -> GetMultiTablePageRequest name tables max def -> ShowS
showsPrec :: Int -> GetMultiTablePageRequest name tables max def -> ShowS
$cshow :: forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
GetMultiTablePageRequest name tables max def -> String
show :: GetMultiTablePageRequest name tables max def -> String
$cshowList :: forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Show tables =>
[GetMultiTablePageRequest name tables max def] -> ShowS
showList :: [GetMultiTablePageRequest name tables max def] -> ShowS
Show, GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
(GetMultiTablePageRequest name tables max def
 -> GetMultiTablePageRequest name tables max def -> Bool)
-> (GetMultiTablePageRequest name tables max def
    -> GetMultiTablePageRequest name tables max def -> Bool)
-> Eq (GetMultiTablePageRequest name tables max def)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Eq tables =>
GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
$c== :: forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Eq tables =>
GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
== :: GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
$c/= :: forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Eq tables =>
GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
/= :: GetMultiTablePageRequest name tables max def
-> GetMultiTablePageRequest name tables max def -> Bool
Eq)

-- We can't use deriving via due to this error:
-- .../wire-server/libs/wire-api/src/Wire/API/Routes/MultiTablePaging.hs:24:12: error:
--     • Couldn't match type ‘Data.Singletons.Prelude.Ord.Case_6989586621679792881
--                              1 max (CmpNat 1 max)’
--                      with ‘'True’
--         arising from the 'deriving' clause of a data type declaration
--     • When deriving the instance for (ToJSON
--                                         (GetMultiTablePageRequest name tables max def))
--    |
-- 24 |   deriving ToJSON via Schema (GetMultiTablePageRequest name tables max def)
--    |            ^^^^^^

type RequestSchemaConstraint name tables max def = (KnownNat max, KnownNat def, Within Int32 1 max, 1 <= def, def <= max, PagingTable tables, KnownSymbol name)

deriving via
  Schema (GetMultiTablePageRequest name tables max def)
  instance
    (RequestSchemaConstraint name tables max def) => ToJSON (GetMultiTablePageRequest name tables max def)

deriving via
  Schema (GetMultiTablePageRequest name tables max def)
  instance
    (RequestSchemaConstraint name tables max def) => FromJSON (GetMultiTablePageRequest name tables max def)

deriving via
  Schema (GetMultiTablePageRequest name tables max def)
  instance
    ( Typeable tables,
      RequestSchemaConstraint name tables max def
    ) =>
    S.ToSchema (GetMultiTablePageRequest name tables max def)

instance (RequestSchemaConstraint name tables max def) => ToSchema (GetMultiTablePageRequest name tables max def) where
  schema :: ValueSchema
  NamedSwaggerDoc (GetMultiTablePageRequest name tables max def)
schema =
    let addPagingStateDoc :: NamedSwaggerDoc -> NamedSwaggerDoc
addPagingStateDoc =
          (Maybe Text -> Identity (Maybe Text))
-> NamedSwaggerDoc -> Identity NamedSwaggerDoc
forall s a. HasDescription s a => Lens' s a
Lens' NamedSwaggerDoc (Maybe Text)
description
            ((Maybe Text -> Identity (Maybe Text))
 -> NamedSwaggerDoc -> Identity NamedSwaggerDoc)
-> Text -> NamedSwaggerDoc -> NamedSwaggerDoc
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Text
"optional, when not specified, the first page will be returned.\
               \Every returned page contains a paging_state, this should be supplied to retrieve the next page."
        addSizeDoc :: NamedSwaggerDoc -> NamedSwaggerDoc
addSizeDoc = (Maybe Text -> Identity (Maybe Text))
-> NamedSwaggerDoc -> Identity NamedSwaggerDoc
forall s a. HasDescription s a => Lens' s a
Lens' NamedSwaggerDoc (Maybe Text)
description ((Maybe Text -> Identity (Maybe Text))
 -> NamedSwaggerDoc -> Identity NamedSwaggerDoc)
-> Text -> NamedSwaggerDoc -> NamedSwaggerDoc
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ (Text
"optional, must be <= " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> forall (n :: Nat). KnownNat n => Text
textFromNat @max Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
", defaults to " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> forall (n :: Nat). KnownNat n => Text
textFromNat @def Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".")
     in Text
-> (NamedSwaggerDoc -> NamedSwaggerDoc)
-> ObjectSchema
     SwaggerDoc (GetMultiTablePageRequest name tables max def)
-> ValueSchema
     NamedSwaggerDoc (GetMultiTablePageRequest name tables max def)
forall doc doc' a.
HasObject doc doc' =>
Text -> (doc' -> doc') -> ObjectSchema doc a -> ValueSchema doc' a
objectWithDocModifier
          (Text
"GetPaginated_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> forall (s :: Symbol). KnownSymbol s => Text
textFromSymbol @name)
          ((Maybe Text -> Identity (Maybe Text))
-> NamedSwaggerDoc -> Identity NamedSwaggerDoc
forall s a. HasDescription s a => Lens' s a
Lens' NamedSwaggerDoc (Maybe Text)
description ((Maybe Text -> Identity (Maybe Text))
 -> NamedSwaggerDoc -> Identity NamedSwaggerDoc)
-> Text -> NamedSwaggerDoc -> NamedSwaggerDoc
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Text
"A request to list some or all of a user's " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> forall (s :: Symbol). KnownSymbol s => Text
textFromSymbol @name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
", including remote ones")
          (ObjectSchema
   SwaggerDoc (GetMultiTablePageRequest name tables max def)
 -> ValueSchema
      NamedSwaggerDoc (GetMultiTablePageRequest name tables max def))
-> ObjectSchema
     SwaggerDoc (GetMultiTablePageRequest name tables max def)
-> ValueSchema
     NamedSwaggerDoc (GetMultiTablePageRequest name tables max def)
forall a b. (a -> b) -> a -> b
$ Range 1 max Int32
-> Maybe (MultiTablePagingState name tables)
-> GetMultiTablePageRequest name tables max def
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
Range 1 max Int32
-> Maybe (MultiTablePagingState name tables)
-> GetMultiTablePageRequest name tables max def
GetMultiTablePageRequest
            (Range 1 max Int32
 -> Maybe (MultiTablePagingState name tables)
 -> GetMultiTablePageRequest name tables max def)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     (Range 1 max Int32)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     (Maybe (MultiTablePagingState name tables)
      -> GetMultiTablePageRequest name tables max def)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GetMultiTablePageRequest name tables max def -> Range 1 max Int32
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
GetMultiTablePageRequest name tables max def -> Range 1 max Int32
gmtprSize (GetMultiTablePageRequest name tables max def -> Range 1 max Int32)
-> SchemaP
     SwaggerDoc Object [Pair] (Range 1 max Int32) (Range 1 max Int32)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     (Range 1 max Int32)
forall (p :: * -> * -> *) a a' b.
Profunctor p =>
(a -> a') -> p a' b -> p a b
.= (Range 1 max Int32 -> Maybe (Range 1 max Int32) -> Range 1 max Int32
forall a. a -> Maybe a -> a
fromMaybe (Proxy def -> Range 1 max Int32
forall (n :: Nat) (x :: Nat) (m :: Nat) a.
(n <= x, x <= m, KnownNat x, Num a) =>
Proxy x -> Range n m a
toRange (forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @def)) (Maybe (Range 1 max Int32) -> Range 1 max Int32)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (Range 1 max Int32)
     (Maybe (Range 1 max Int32))
-> SchemaP
     SwaggerDoc Object [Pair] (Range 1 max Int32) (Range 1 max Int32)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text
-> (NamedSwaggerDoc -> NamedSwaggerDoc)
-> SchemaP
     NamedSwaggerDoc Value Value (Range 1 max Int32) (Range 1 max Int32)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (Range 1 max Int32)
     (Maybe (Range 1 max Int32))
forall doc doc' a b.
(HasOpt doc, HasField doc' doc) =>
Text
-> (doc' -> doc')
-> SchemaP doc' Value Value a b
-> SchemaP doc Object [Pair] a (Maybe b)
optFieldWithDocModifier Text
"size" NamedSwaggerDoc -> NamedSwaggerDoc
addSizeDoc SchemaP
  NamedSwaggerDoc Value Value (Range 1 max Int32) (Range 1 max Int32)
forall a. ToSchema a => ValueSchema NamedSwaggerDoc a
schema)
            SchemaP
  SwaggerDoc
  Object
  [Pair]
  (GetMultiTablePageRequest name tables max def)
  (Maybe (MultiTablePagingState name tables)
   -> GetMultiTablePageRequest name tables max def)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     (Maybe (MultiTablePagingState name tables))
-> ObjectSchema
     SwaggerDoc (GetMultiTablePageRequest name tables max def)
forall a b.
SchemaP
  SwaggerDoc
  Object
  [Pair]
  (GetMultiTablePageRequest name tables max def)
  (a -> b)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     a
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> GetMultiTablePageRequest name tables max def
-> Maybe (MultiTablePagingState name tables)
forall (name :: Symbol) tables (max :: Nat) (def :: Nat).
GetMultiTablePageRequest name tables max def
-> Maybe (MultiTablePagingState name tables)
gmtprState (GetMultiTablePageRequest name tables max def
 -> Maybe (MultiTablePagingState name tables))
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (Maybe (MultiTablePagingState name tables))
     (Maybe (MultiTablePagingState name tables))
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (GetMultiTablePageRequest name tables max def)
     (Maybe (MultiTablePagingState name tables))
forall (p :: * -> * -> *) a a' b.
Profunctor p =>
(a -> a') -> p a' b -> p a b
.= SchemaP
  SwaggerDoc
  Object
  [Pair]
  (MultiTablePagingState name tables)
  (Maybe (MultiTablePagingState name tables))
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (Maybe (MultiTablePagingState name tables))
     (Maybe (MultiTablePagingState name tables))
forall w d v a b.
Monoid w =>
SchemaP d v w a b -> SchemaP d v w (Maybe a) b
maybe_ (Text
-> (NamedSwaggerDoc -> NamedSwaggerDoc)
-> SchemaP
     NamedSwaggerDoc
     Value
     Value
     (MultiTablePagingState name tables)
     (MultiTablePagingState name tables)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePagingState name tables)
     (Maybe (MultiTablePagingState name tables))
forall doc doc' a b.
(HasOpt doc, HasField doc' doc) =>
Text
-> (doc' -> doc')
-> SchemaP doc' Value Value a b
-> SchemaP doc Object [Pair] a (Maybe b)
optFieldWithDocModifier Text
"paging_state" NamedSwaggerDoc -> NamedSwaggerDoc
addPagingStateDoc SchemaP
  NamedSwaggerDoc
  Value
  Value
  (MultiTablePagingState name tables)
  (MultiTablePagingState name tables)
forall a. ToSchema a => ValueSchema NamedSwaggerDoc a
schema)

textFromNat :: forall n. (KnownNat n) => Text
textFromNat :: forall (n :: Nat). KnownNat n => Text
textFromNat = String -> Text
Text.pack (String -> Text) -> (Proxy n -> String) -> Proxy n -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> String
forall a. Show a => a -> String
show (Integer -> String) -> (Proxy n -> Integer) -> Proxy n -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Text) -> Proxy n -> Text
forall a b. (a -> b) -> a -> b
$ forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n

textFromSymbol :: forall s. (KnownSymbol s) => Text
textFromSymbol :: forall (s :: Symbol). KnownSymbol s => Text
textFromSymbol = String -> Text
Text.pack (String -> Text) -> (Proxy s -> String) -> Proxy s -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy s -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy s -> Text) -> Proxy s -> Text
forall a b. (a -> b) -> a -> b
$ forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @s

-- | The result of a multi-table paginated query. Contains the list of results,
-- a flag indicating whether there are more, and the state to pass to the next
-- query.
data MultiTablePage (name :: Symbol) (resultsKey :: Symbol) (tables :: Type) a = MultiTablePage
  { forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a -> [a]
mtpResults :: [a],
    forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a -> Bool
mtpHasMore :: Bool,
    forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a
-> MultiTablePagingState name tables
mtpPagingState :: MultiTablePagingState name tables
  }
  deriving stock (MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
(MultiTablePage name resultsKey tables a
 -> MultiTablePage name resultsKey tables a -> Bool)
-> (MultiTablePage name resultsKey tables a
    -> MultiTablePage name resultsKey tables a -> Bool)
-> Eq (MultiTablePage name resultsKey tables a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Eq a, Eq tables) =>
MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
$c== :: forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Eq a, Eq tables) =>
MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
== :: MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
$c/= :: forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Eq a, Eq tables) =>
MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
/= :: MultiTablePage name resultsKey tables a
-> MultiTablePage name resultsKey tables a -> Bool
Eq, Int -> MultiTablePage name resultsKey tables a -> ShowS
[MultiTablePage name resultsKey tables a] -> ShowS
MultiTablePage name resultsKey tables a -> String
(Int -> MultiTablePage name resultsKey tables a -> ShowS)
-> (MultiTablePage name resultsKey tables a -> String)
-> ([MultiTablePage name resultsKey tables a] -> ShowS)
-> Show (MultiTablePage name resultsKey tables a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
Int -> MultiTablePage name resultsKey tables a -> ShowS
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
[MultiTablePage name resultsKey tables a] -> ShowS
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
MultiTablePage name resultsKey tables a -> String
$cshowsPrec :: forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
Int -> MultiTablePage name resultsKey tables a -> ShowS
showsPrec :: Int -> MultiTablePage name resultsKey tables a -> ShowS
$cshow :: forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
MultiTablePage name resultsKey tables a -> String
show :: MultiTablePage name resultsKey tables a -> String
$cshowList :: forall (name :: Symbol) (resultsKey :: Symbol) tables a.
(Show a, Show tables) =>
[MultiTablePage name resultsKey tables a] -> ShowS
showList :: [MultiTablePage name resultsKey tables a] -> ShowS
Show)

type PageSchemaConstraints name resultsKey tables a = (KnownSymbol resultsKey, KnownSymbol name, ToSchema a, PagingTable tables)

deriving via
  (Schema (MultiTablePage name resultsKey tables a))
  instance
    (PageSchemaConstraints name resultsKey tables a) =>
    ToJSON (MultiTablePage name resultsKey tables a)

deriving via
  (Schema (MultiTablePage name resultsKey tables a))
  instance
    (PageSchemaConstraints name resultsKey tables a) =>
    FromJSON (MultiTablePage name resultsKey tables a)

deriving via
  (Schema (MultiTablePage name resultsKey tables a))
  instance
    (Typeable tables, Typeable a, PageSchemaConstraints name resultsKey tables a) =>
    S.ToSchema (MultiTablePage name resultsKey tables a)

instance
  (KnownSymbol resultsKey, KnownSymbol name, ToSchema a, PagingTable tables) =>
  ToSchema (MultiTablePage name resultsKey tables a)
  where
  schema :: ValueSchema
  NamedSwaggerDoc (MultiTablePage name resultsKey tables a)
schema =
    Text
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePage name resultsKey tables a)
-> ValueSchema
     NamedSwaggerDoc (MultiTablePage name resultsKey tables a)
forall doc doc' a b.
HasObject doc doc' =>
Text
-> SchemaP doc Object [Pair] a b -> SchemaP doc' Value Value a b
object (forall (s :: Symbol). KnownSymbol s => Text
textFromSymbol @name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_Page") (SchemaP
   SwaggerDoc
   Object
   [Pair]
   (MultiTablePage name resultsKey tables a)
   (MultiTablePage name resultsKey tables a)
 -> ValueSchema
      NamedSwaggerDoc (MultiTablePage name resultsKey tables a))
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePage name resultsKey tables a)
-> ValueSchema
     NamedSwaggerDoc (MultiTablePage name resultsKey tables a)
forall a b. (a -> b) -> a -> b
$
      [a]
-> Bool
-> MultiTablePagingState name tables
-> MultiTablePage name resultsKey tables a
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
[a]
-> Bool
-> MultiTablePagingState name tables
-> MultiTablePage name resultsKey tables a
MultiTablePage
        ([a]
 -> Bool
 -> MultiTablePagingState name tables
 -> MultiTablePage name resultsKey tables a)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     [a]
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (Bool
      -> MultiTablePagingState name tables
      -> MultiTablePage name resultsKey tables a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MultiTablePage name resultsKey tables a -> [a]
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a -> [a]
mtpResults (MultiTablePage name resultsKey tables a -> [a])
-> SchemaP SwaggerDoc Object [Pair] [a] [a]
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     [a]
forall (p :: * -> * -> *) a a' b.
Profunctor p =>
(a -> a') -> p a' b -> p a b
.= Text
-> SchemaP SwaggerDoc Value Value [a] [a]
-> SchemaP SwaggerDoc Object [Pair] [a] [a]
forall doc' doc a b.
HasField doc' doc =>
Text
-> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b
field (forall (s :: Symbol). KnownSymbol s => Text
textFromSymbol @resultsKey) (ValueSchema NamedSwaggerDoc a
-> SchemaP SwaggerDoc Value Value [a] [a]
forall ndoc doc a.
(HasArray ndoc doc, HasName ndoc) =>
ValueSchema ndoc a -> ValueSchema doc [a]
array ValueSchema NamedSwaggerDoc a
forall a. ToSchema a => ValueSchema NamedSwaggerDoc a
schema)
        SchemaP
  SwaggerDoc
  Object
  [Pair]
  (MultiTablePage name resultsKey tables a)
  (Bool
   -> MultiTablePagingState name tables
   -> MultiTablePage name resultsKey tables a)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     Bool
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePagingState name tables
      -> MultiTablePage name resultsKey tables a)
forall a b.
SchemaP
  SwaggerDoc
  Object
  [Pair]
  (MultiTablePage name resultsKey tables a)
  (a -> b)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     a
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MultiTablePage name resultsKey tables a -> Bool
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a -> Bool
mtpHasMore (MultiTablePage name resultsKey tables a -> Bool)
-> SchemaP SwaggerDoc Object [Pair] Bool Bool
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     Bool
forall (p :: * -> * -> *) a a' b.
Profunctor p =>
(a -> a') -> p a' b -> p a b
.= Text
-> SchemaP NamedSwaggerDoc Value Value Bool Bool
-> SchemaP SwaggerDoc Object [Pair] Bool Bool
forall doc' doc a b.
HasField doc' doc =>
Text
-> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b
field Text
"has_more" SchemaP NamedSwaggerDoc Value Value Bool Bool
forall a. ToSchema a => ValueSchema NamedSwaggerDoc a
schema
        SchemaP
  SwaggerDoc
  Object
  [Pair]
  (MultiTablePage name resultsKey tables a)
  (MultiTablePagingState name tables
   -> MultiTablePage name resultsKey tables a)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePagingState name tables)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePage name resultsKey tables a)
forall a b.
SchemaP
  SwaggerDoc
  Object
  [Pair]
  (MultiTablePage name resultsKey tables a)
  (a -> b)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     a
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> MultiTablePage name resultsKey tables a
-> MultiTablePagingState name tables
forall (name :: Symbol) (resultsKey :: Symbol) tables a.
MultiTablePage name resultsKey tables a
-> MultiTablePagingState name tables
mtpPagingState (MultiTablePage name resultsKey tables a
 -> MultiTablePagingState name tables)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePagingState name tables)
     (MultiTablePagingState name tables)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePage name resultsKey tables a)
     (MultiTablePagingState name tables)
forall (p :: * -> * -> *) a a' b.
Profunctor p =>
(a -> a') -> p a' b -> p a b
.= Text
-> SchemaP
     NamedSwaggerDoc
     Value
     Value
     (MultiTablePagingState name tables)
     (MultiTablePagingState name tables)
-> SchemaP
     SwaggerDoc
     Object
     [Pair]
     (MultiTablePagingState name tables)
     (MultiTablePagingState name tables)
forall doc' doc a b.
HasField doc' doc =>
Text
-> SchemaP doc' Value Value a b -> SchemaP doc Object [Pair] a b
field Text
"paging_state" SchemaP
  NamedSwaggerDoc
  Value
  Value
  (MultiTablePagingState name tables)
  (MultiTablePagingState name tables)
forall a. ToSchema a => ValueSchema NamedSwaggerDoc a
schema

-- | A type to be used as the @tables@ argument of 'GetMultiTablePageRequest'
-- when the resources being paginated through are split into local and remote.
data LocalOrRemoteTable
  = PagingLocals
  | PagingRemotes
  deriving stock (Int -> LocalOrRemoteTable -> ShowS
[LocalOrRemoteTable] -> ShowS
LocalOrRemoteTable -> String
(Int -> LocalOrRemoteTable -> ShowS)
-> (LocalOrRemoteTable -> String)
-> ([LocalOrRemoteTable] -> ShowS)
-> Show LocalOrRemoteTable
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LocalOrRemoteTable -> ShowS
showsPrec :: Int -> LocalOrRemoteTable -> ShowS
$cshow :: LocalOrRemoteTable -> String
show :: LocalOrRemoteTable -> String
$cshowList :: [LocalOrRemoteTable] -> ShowS
showList :: [LocalOrRemoteTable] -> ShowS
Show, LocalOrRemoteTable -> LocalOrRemoteTable -> Bool
(LocalOrRemoteTable -> LocalOrRemoteTable -> Bool)
-> (LocalOrRemoteTable -> LocalOrRemoteTable -> Bool)
-> Eq LocalOrRemoteTable
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LocalOrRemoteTable -> LocalOrRemoteTable -> Bool
== :: LocalOrRemoteTable -> LocalOrRemoteTable -> Bool
$c/= :: LocalOrRemoteTable -> LocalOrRemoteTable -> Bool
/= :: LocalOrRemoteTable -> LocalOrRemoteTable -> Bool
Eq)

instance PagingTable LocalOrRemoteTable where
  encodePagingTable :: LocalOrRemoteTable -> Word8
encodePagingTable LocalOrRemoteTable
PagingLocals = Word8
0
  encodePagingTable LocalOrRemoteTable
PagingRemotes = Word8
1

  decodePagingTable :: forall (m :: * -> *). MonadFail m => Word8 -> m LocalOrRemoteTable
decodePagingTable Word8
0 = LocalOrRemoteTable -> m LocalOrRemoteTable
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LocalOrRemoteTable
PagingLocals
  decodePagingTable Word8
1 = LocalOrRemoteTable -> m LocalOrRemoteTable
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure LocalOrRemoteTable
PagingRemotes
  decodePagingTable Word8
x = String -> m LocalOrRemoteTable
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m LocalOrRemoteTable) -> String -> m LocalOrRemoteTable
forall a b. (a -> b) -> a -> b
$ String
"Expected 0 or 1 while parsing LocalOrRemoteTable, got: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Word8 -> String
forall a. Show a => a -> String
show Word8
x