content: {-# Language OverloadedStrings #-}
  {-|
  Module      : Client.View.Who
  Description : Line renderer for /who replies
  Copyright   : (c) TheDaemoness, 2023
  License     : ISC
  Maintainer  : emertens@gmail.com
  
  This module renders the lines used in /who replies.
  -}
  module Client.View.Who ( whoLines ) where
  
  import           Client.Image.LineWrap (lineWrapPrefix)
  import           Client.Image.Message (IdentifierColorMode(NormalIdentifier), coloredIdentifier, coloredUserInfo, RenderMode (DetailedRender), prettyTime)
  import           Client.Image.PackedImage
  import           Client.Image.Palette
  import           Client.State
  import           Client.State.Network
  import           Client.WhoReply
  import           Control.Lens
  import           Data.Text (Text)
  import qualified Data.Text as Text
  import           Graphics.Vty.Attributes (defAttr)
  import           Irc.Identifier
  import qualified Data.HashMap.Strict as HashMap
  import Client.Image.MircFormatting (parseIrcText')
  import Client.State.Focus (Focus(NetworkFocus))
  
  -- |
  -- | Render the lines used by the @/who@ command in normal mode.
  whoLines ::
    Text        {- ^ network           -} ->
    Int         {- ^ window width      -} ->
    ClientState {- ^ client state      -} ->
    [Image']
  whoLines network width st =
    -- TODO: This pattern exists in a few other views. Maybe deduplicate?
    case preview (clientConnection network) st of
      Just cs -> whoLines' cs width st
      Nothing -> [text' (view palError pal) "No connection"]
    where
      pal = clientPalette st
  
  whoLines' :: NetworkState -> Int -> ClientState -> [Image']
  whoLines' cs width st
    | Text.null $ view (csWhoReply . whoQuery . _1) cs = [text' (view palError pal) "No previous WHO query"]
    | whorpl^.whoDone = countImage <> queryPart : images
    | otherwise = countImagePending <> queryPart : images
    where
      pal = clientPalette st
      whorpl = view csWhoReply cs
      (query, arg) = view whoQuery whorpl
      entries = view whoItems whorpl
      entries' = clientFilter st whoFilterText entries
  
      images = concatMap renderEntry entries'
      renderEntry :: WhoReplyItem -> [Image']
      renderEntry entry = reverse $ lineWrapPrefix width (renderPrefix entry) (renderSuffix entry)
      -- Skipping rendering the channel because it doesn't add anything most of the time.
      renderPrefix entry = coloredUserInfo pal DetailedRender hilites (view whoUserInfo entry)
        where hilites = clientHighlightsFocus (NetworkFocus (view csNetwork cs)) st
      renderSuffix :: WhoReplyItem -> Image'
      renderSuffix entry = mconcat $ mapJoinWhoFields entry
        (const mempty)
        (label "$a:" . identifier)
        (label "ip: " . text' defAttr)
        (label "server: " . identifier)
        (label "away" $ text' defAttr "")
        (label "flags: " . text' (view palSigil pal))
        (label "hops: " . string defAttr . show)
        (label "idle: " . string defAttr . prettyTime 1)
        (label "oplvl: " . text' defAttr)
        (label "gecos: " . parseIrcText' False pal)
  
      countImagePending = countImage <> text' (view palLabel pal) "..."
      countImage = text' (view palLabel pal) "Users in " <>
                   coloredIdentifier pal NormalIdentifier HashMap.empty (mkId query) <>
                   text' (view palLabel pal) " (visible/total): " <>
                   string defAttr (show (length entries')) <>
                   char (view palLabel pal) '/' <>
                   string defAttr (show (length entries))
      queryPart = case arg of
        Just txt | not (Text.null txt) -> label " Options: " $ text' defAttr txt
        _ -> text' defAttr ""
  
      label txt image = text' (view palLabel pal) txt <> image <> text' defAttr " "
      -- Don't use hilites here; the identifiers are never the user's nick.
      identifier = coloredIdentifier pal NormalIdentifier HashMap.empty
  