-- | Pagination utilities

{-# OPTIONS_HADDOCK hide #-}

module Blockfrost.Util.Pagination
  ( Paged (..)
  , Pagination
  , PaginationExpanded
  , page
  , paged
  , nextPage
  , maxPageSize
  ) where

import Data.Default.Class
import Servant.API (QueryParam, (:>))

-- | Pagination parameters
data Paged = Paged
  { Paged -> Int
countPerPage :: Int -- ^ Count of results per page
  , Paged -> Int
pageNumber   :: Int -- ^ Page number
  } deriving (Paged -> Paged -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Paged -> Paged -> Bool
$c/= :: Paged -> Paged -> Bool
== :: Paged -> Paged -> Bool
$c== :: Paged -> Paged -> Bool
Eq, Eq Paged
Paged -> Paged -> Bool
Paged -> Paged -> Ordering
Paged -> Paged -> Paged
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
min :: Paged -> Paged -> Paged
$cmin :: Paged -> Paged -> Paged
max :: Paged -> Paged -> Paged
$cmax :: Paged -> Paged -> Paged
>= :: Paged -> Paged -> Bool
$c>= :: Paged -> Paged -> Bool
> :: Paged -> Paged -> Bool
$c> :: Paged -> Paged -> Bool
<= :: Paged -> Paged -> Bool
$c<= :: Paged -> Paged -> Bool
< :: Paged -> Paged -> Bool
$c< :: Paged -> Paged -> Bool
compare :: Paged -> Paged -> Ordering
$ccompare :: Paged -> Paged -> Ordering
Ord, Int -> Paged -> ShowS
[Paged] -> ShowS
Paged -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Paged] -> ShowS
$cshowList :: [Paged] -> ShowS
show :: Paged -> String
$cshow :: Paged -> String
showsPrec :: Int -> Paged -> ShowS
$cshowsPrec :: Int -> Paged -> ShowS
Show)

-- | Maximum number of items per page
maxPageSize :: Int
maxPageSize :: Int
maxPageSize = Int
100

instance Default Paged where
  def :: Paged
def = Int -> Int -> Paged
Paged Int
maxPageSize Int
1

-- | Default `Paged` at specific page number
page :: Int -> Paged
page :: Int -> Paged
page Int
n | Int
n forall a. Ord a => a -> a -> Bool
>= Int
1 = forall a. Default a => a
def { pageNumber :: Int
pageNumber = Int
n }
page Int
_ = forall a. HasCallStack => String -> a
error String
"Page number not in range [1..]"

-- | Construct `Paged` from page size and page number.
--
-- Throws error on invalid values.
paged :: Int -> Int -> Paged
paged :: Int -> Int -> Paged
paged Int
size Int
_ | Int
size forall a. Ord a => a -> a -> Bool
> Int
maxPageSize = forall a. HasCallStack => String -> a
error String
"Page size exceeds 100"
paged Int
_ Int
n | Int
n forall a. Ord a => a -> a -> Bool
< Int
1 = forall a. HasCallStack => String -> a
error String
"Page number not in range [1..]"
paged Int
size Int
n = Int -> Int -> Paged
Paged Int
size Int
n

-- | Increment page number
nextPage :: Paged -> Paged
nextPage :: Paged -> Paged
nextPage Paged
p = Paged
p { pageNumber :: Int
pageNumber = Int
1 forall a. Num a => a -> a -> a
+ Paged -> Int
pageNumber Paged
p }

-- | Adds Pagination to an API
data Pagination

type PaginationExpanded subApi =
     QueryParam "count" Int
  :> QueryParam "page" Int
  :> subApi