module Matterhorn.State.ChannelListOverlay
  ( enterChannelListOverlayMode

  , 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           Lens.Micro.Platform ( to )

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

import           Matterhorn.State.ListOverlay
import           Matterhorn.State.Channels
import           Matterhorn.Types


enterChannelListOverlayMode :: MH ()
enterChannelListOverlayMode :: MH ()
enterChannelListOverlayMode = do
    TeamId
myTId <- Getting TeamId ChatState TeamId -> MH TeamId
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting TeamId ChatState TeamId
SimpleGetter ChatState TeamId
csCurrentTeamId
    [ChannelId]
myChannels <- Getting [ChannelId] ChatState [ChannelId] -> MH [ChannelId]
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use ((ClientChannels -> Const [ChannelId] ClientChannels)
-> ChatState -> Const [ChannelId] ChatState
Lens' ChatState ClientChannels
csChannels((ClientChannels -> Const [ChannelId] ClientChannels)
 -> ChatState -> Const [ChannelId] ChatState)
-> (([ChannelId] -> Const [ChannelId] [ChannelId])
    -> ClientChannels -> Const [ChannelId] ClientChannels)
-> Getting [ChannelId] ChatState [ChannelId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ClientChannels -> [ChannelId])
-> SimpleGetter ClientChannels [ChannelId]
forall s a. (s -> a) -> SimpleGetter s a
to ((ClientChannel -> Bool) -> ClientChannels -> [ChannelId]
filteredChannelIds (Bool -> ClientChannel -> Bool
forall a b. a -> b -> a
const Bool
True)))
    Lens' ChatState (ListOverlayState Channel ChannelSearchScope)
-> Mode
-> ChannelSearchScope
-> (Channel -> MH Bool)
-> (ChannelSearchScope -> Session -> Text -> IO (Vector Channel))
-> MH ()
forall a b.
Lens' ChatState (ListOverlayState a b)
-> Mode
-> b
-> (a -> MH Bool)
-> (b -> Session -> Text -> IO (Vector a))
-> MH ()
enterListOverlayMode (TeamId -> Lens' ChatState TeamState
csTeam(TeamId
myTId)((TeamState -> f TeamState) -> ChatState -> f ChatState)
-> ((ListOverlayState Channel ChannelSearchScope
     -> f (ListOverlayState Channel ChannelSearchScope))
    -> TeamState -> f TeamState)
-> (ListOverlayState Channel ChannelSearchScope
    -> f (ListOverlayState Channel ChannelSearchScope))
-> ChatState
-> f ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ListOverlayState Channel ChannelSearchScope
 -> f (ListOverlayState Channel ChannelSearchScope))
-> TeamState -> f TeamState
Lens' TeamState (ListOverlayState Channel ChannelSearchScope)
tsChannelListOverlay) Mode
ChannelListOverlay
        ChannelSearchScope
AllChannels Channel -> MH Bool
enterHandler (TeamId
-> [ChannelId]
-> ChannelSearchScope
-> Session
-> Text
-> IO (Vector Channel)
fetchResults TeamId
myTId [ChannelId]
myChannels)

enterHandler :: Channel -> MH Bool
enterHandler :: Channel -> MH Bool
enterHandler Channel
chan = do
    ChannelId -> MH ()
joinChannel (Channel -> ChannelId
forall x y. HasId x y => x -> y
getId Channel
chan)
    Bool -> MH Bool
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 <- TeamId -> Text -> Session -> IO (Seq Channel)
MM.mmSearchChannels TeamId
myTId Text
searchString Session
session
    let filteredChans :: Seq Channel
filteredChans = (Channel -> Bool) -> Seq Channel -> Seq Channel
forall a. (a -> Bool) -> Seq a -> Seq a
Seq.filter (\ Channel
c -> Bool -> Bool
not (Channel -> ChannelId
channelId Channel
c ChannelId -> [ChannelId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ChannelId]
exclude)) Seq Channel
resultChans
        sortedChans :: Vector Channel
sortedChans = [Channel] -> Vector Channel
forall a. [a] -> Vector a
Vec.fromList ([Channel] -> Vector Channel) -> [Channel] -> Vector Channel
forall a b. (a -> b) -> a -> b
$ Seq Channel -> [Channel]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq Channel -> [Channel]) -> Seq Channel -> [Channel]
forall a b. (a -> b) -> a -> b
$ (Channel -> Channel -> Ordering) -> Seq Channel -> Seq Channel
forall a. (a -> a -> Ordering) -> Seq a -> Seq a
Seq.sortBy (UserText -> UserText -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (UserText -> UserText -> Ordering)
-> (Channel -> UserText) -> Channel -> Channel -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Channel -> UserText
channelName) Seq Channel
filteredChans
    Vector Channel -> IO (Vector Channel)
forall (m :: * -> *) a. Monad m => a -> m a
return Vector Channel
sortedChans

-- | Move the selection up in the channel list overlay by one channel.
channelListSelectUp :: MH ()
channelListSelectUp :: MH ()
channelListSelectUp = (List Name Channel -> List Name Channel) -> MH ()
channelListMove List Name Channel -> List Name Channel
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 overlay by one channel.
channelListSelectDown :: MH ()
channelListSelectDown :: MH ()
channelListSelectDown = (List Name Channel -> List Name Channel) -> MH ()
channelListMove List Name Channel -> List Name Channel
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 overlay by a page of channels
-- (channelListPageSize).
channelListPageUp :: MH ()
channelListPageUp :: MH ()
channelListPageUp = (List Name Channel -> List Name Channel) -> MH ()
channelListMove (Int -> List Name Channel -> List Name Channel
forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
Int -> GenericList n t e -> GenericList n t e
L.listMoveBy (-Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
channelListPageSize))

-- | Move the selection down in the channel list overlay by a page of channels
-- (channelListPageSize).
channelListPageDown :: MH ()
channelListPageDown :: MH ()
channelListPageDown = (List Name Channel -> List Name Channel) -> MH ()
channelListMove (Int -> List Name Channel -> List Name Channel
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 :: (L.List Name Channel -> L.List Name Channel) -> MH ()
channelListMove :: (List Name Channel -> List Name Channel) -> MH ()
channelListMove = Lens' ChatState (ListOverlayState Channel ChannelSearchScope)
-> (List Name Channel -> List Name Channel) -> MH ()
forall a b.
Lens' ChatState (ListOverlayState a b)
-> (List Name a -> List Name a) -> MH ()
listOverlayMove ((TeamState -> f TeamState) -> ChatState -> f ChatState
Lens' ChatState TeamState
csCurrentTeam((TeamState -> f TeamState) -> ChatState -> f ChatState)
-> ((ListOverlayState Channel ChannelSearchScope
     -> f (ListOverlayState Channel ChannelSearchScope))
    -> TeamState -> f TeamState)
-> (ListOverlayState Channel ChannelSearchScope
    -> f (ListOverlayState Channel ChannelSearchScope))
-> ChatState
-> f ChatState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(ListOverlayState Channel ChannelSearchScope
 -> f (ListOverlayState Channel ChannelSearchScope))
-> TeamState -> f TeamState
Lens' TeamState (ListOverlayState Channel ChannelSearchScope)
tsChannelListOverlay)

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