module Matterhorn.State.ChannelListWindow
  ( enterChannelListWindowMode

  , channelListSelectDown
  , channelListSelectUp
  , channelListPageDown
  , channelListPageUp
  )
where

import           Prelude ()
import           Matterhorn.Prelude

import qualified Brick.Widgets.List as L
import qualified Data.Vector as Vec
import qualified Data.Sequence as Seq
import           Data.Function ( on )
import qualified Data.Text as T
import           Lens.Micro.Platform ( to )

import           Network.Mattermost.Types
import qualified Network.Mattermost.Endpoints as MM

import           Matterhorn.State.ListWindow
import           Matterhorn.State.Channels
import           Matterhorn.Types


enterChannelListWindowMode :: TeamId -> MH ()
enterChannelListWindowMode :: TeamId -> MH ()
enterChannelListWindowMode TeamId
tId = do
    [ChannelId]
myChannels <- forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Lens' ChatState ClientChannels
csChannelsforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall s a. (s -> a) -> SimpleGetter s a
to ((ClientChannel -> Bool) -> ClientChannels -> [ChannelId]
filteredChannelIds (forall a b. a -> b -> a
const Bool
True)))
    forall a b.
TeamId
-> Lens' ChatState (ListWindowState a b)
-> Mode
-> b
-> (a -> MH Bool)
-> (b -> Session -> Text -> IO (Vector a))
-> MH ()
enterListWindowMode TeamId
tId (TeamId -> Lens' ChatState TeamState
csTeam(TeamId
tId)forall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' TeamState (ListWindowState Channel ChannelSearchScope)
tsChannelListWindow) Mode
ChannelListWindow
        ChannelSearchScope
AllChannels (TeamId -> Channel -> MH Bool
enterHandler TeamId
tId) (TeamId
-> [ChannelId]
-> ChannelSearchScope
-> Session
-> Text
-> IO (Vector Channel)
fetchResults TeamId
tId [ChannelId]
myChannels)

enterHandler :: TeamId -> Channel -> MH Bool
enterHandler :: TeamId -> Channel -> MH Bool
enterHandler TeamId
tId Channel
chan = do
    TeamId -> ChannelId -> MH ()
joinChannel TeamId
tId (forall x y. HasId x y => x -> y
getId Channel
chan)
    TeamId -> MH ()
popMode TeamId
tId
    forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True

fetchResults :: TeamId
             -> [ChannelId]
             -- ^ The channels to exclude from the results
             -> ChannelSearchScope
             -- ^ The scope to search
             -> Session
             -- ^ The connection session
             -> Text
             -- ^ The search string
             -> IO (Vec.Vector Channel)
fetchResults :: TeamId
-> [ChannelId]
-> ChannelSearchScope
-> Session
-> Text
-> IO (Vector Channel)
fetchResults TeamId
myTId [ChannelId]
exclude ChannelSearchScope
AllChannels Session
session Text
searchString = do
    Seq Channel
resultChans <- case Text -> Bool
T.null Text
searchString of
        Bool
True -> TeamId -> Maybe Int -> Maybe Int -> Session -> IO (Seq Channel)
MM.mmGetPublicChannels TeamId
myTId (forall a. a -> Maybe a
Just Int
0) (forall a. a -> Maybe a
Just Int
200) Session
session
        Bool
False -> TeamId -> Text -> Session -> IO (Seq Channel)
MM.mmSearchChannels TeamId
myTId Text
searchString Session
session
    let filteredChans :: Seq Channel
filteredChans = forall a. (a -> Bool) -> Seq a -> Seq a
Seq.filter (\ Channel
c -> Bool -> Bool
not (Channel -> ChannelId
channelId Channel
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ChannelId]
exclude)) Seq Channel
resultChans
        sortedChans :: Vector Channel
sortedChans = forall a. [a] -> Vector a
Vec.fromList forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> [a]
toList forall a b. (a -> b) -> a -> b
$ forall a. (a -> a -> Ordering) -> Seq a -> Seq a
Seq.sortBy (forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Channel -> UserText
channelDisplayName) Seq Channel
filteredChans
    forall (m :: * -> *) a. Monad m => a -> m a
return Vector Channel
sortedChans

-- | Move the selection up in the channel list window by one channel.
channelListSelectUp :: TeamId -> MH ()
channelListSelectUp :: TeamId -> MH ()
channelListSelectUp TeamId
tId = TeamId -> (List Name Channel -> List Name Channel) -> MH ()
channelListMove TeamId
tId forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
GenericList n t e -> GenericList n t e
L.listMoveUp

-- | Move the selection down in the channel list window by one channel.
channelListSelectDown :: TeamId -> MH ()
channelListSelectDown :: TeamId -> MH ()
channelListSelectDown TeamId
tId = TeamId -> (List Name Channel -> List Name Channel) -> MH ()
channelListMove TeamId
tId forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
GenericList n t e -> GenericList n t e
L.listMoveDown

-- | Move the selection up in the channel list window by a page of channels
-- (channelListPageSize).
channelListPageUp :: TeamId -> MH ()
channelListPageUp :: TeamId -> MH ()
channelListPageUp TeamId
tId = TeamId -> (List Name Channel -> List Name Channel) -> MH ()
channelListMove TeamId
tId (forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
Int -> GenericList n t e -> GenericList n t e
L.listMoveBy (-Int
1 forall a. Num a => a -> a -> a
* Int
channelListPageSize))

-- | Move the selection down in the channel list window by a page of channels
-- (channelListPageSize).
channelListPageDown :: TeamId -> MH ()
channelListPageDown :: TeamId -> MH ()
channelListPageDown TeamId
tId = TeamId -> (List Name Channel -> List Name Channel) -> MH ()
channelListMove TeamId
tId (forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
Int -> GenericList n t e -> GenericList n t e
L.listMoveBy Int
channelListPageSize)

-- | Transform the channel list results in some way, e.g. by moving the
-- cursor, and then check to see whether the modification warrants a
-- prefetch of more search results.
channelListMove :: TeamId -> (L.List Name Channel -> L.List Name Channel) -> MH ()
channelListMove :: TeamId -> (List Name Channel -> List Name Channel) -> MH ()
channelListMove TeamId
tId = forall a b.
Lens' ChatState (ListWindowState a b)
-> (List Name a -> List Name a) -> MH ()
listWindowMove (TeamId -> Lens' ChatState TeamState
csTeam(TeamId
tId)forall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' TeamState (ListWindowState Channel ChannelSearchScope)
tsChannelListWindow)

-- | The number of channels in a "page" for cursor movement purposes.
channelListPageSize :: Int
channelListPageSize :: Int
channelListPageSize = Int
10