{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS -fno-warn-name-shadowing -fno-warn-unused-do-bind #-}

-- | Simple pagination support for blaze.

module Text.Blaze.Pagination where

import           Control.Monad
import           Data.Maybe
import           Data.Pagination
import           Network.URI
import           Network.URI.Params
import qualified Prelude                     as P
import           Prelude                     hiding (div,span)
import           Safe
import           Text.Blaze.Extra
import           Text.Blaze.Html5            as H hiding (map)
import           Text.Blaze.Html5.Attributes as A hiding (form,span,min,max)

-- | Render pagination as html.
pagination :: URI -> Pagination -> Html
pagination uri pn@Pagination{..} =
  div !. "pagination" $ do
    when pnShowDesc description
    chooser
  
  where description = do
         span !. "description" $ do
           "Showing "
           toHtml ((pnCurrentPage-1)*pnPerPage + 1)
           "–"
           toHtml (min pnTotal (pnCurrentPage * pnPerPage))
           " of "
           toHtml (pnTotal)
           " results"
        
        chooser = do
          div !. "pages" $ do
            ul !. "pages-list" $ do
              when (pnCurrentPage > 1) $
                li !. "page" $ a ! hrefSet uri paramName (show (pnCurrentPage-1)) $
                  "Previous"
              let w = 10 :: Integer
                  start = max 1 (pnCurrentPage - (w // 2))
                  end = min (pageCount) (start + w)
              forM_ [start..end] $ \i ->
                li !. "page" $ do
                  let theclass = if i == pnCurrentPage then "current" else ""
                  a ! hrefSet uri paramName (show i) !. theclass $
                    toHtml (show i)
              when (end < pageCount) $
                li !. "page" $ "…"
              when (pnCurrentPage < pageCount) $
                li !. "page" $ a ! hrefSet uri paramName (show (pnCurrentPage+1)) $
                  "Next"
              
        paramName = pnName ++ "_page"
        
        (//) = P.div
        pageCount = pnPageCount pn