module Matterhorn.State.ThemeListWindow
  ( enterThemeListMode

  , themeListSelectDown
  , themeListSelectUp
  , themeListPageDown
  , themeListPageUp

  , setTheme
  )
where

import           Prelude ()
import           Matterhorn.Prelude

import           Brick ( invalidateCache )
import           Brick.Themes ( themeToAttrMap )
import qualified Brick.Widgets.List as L
import qualified Data.Text as T
import qualified Data.Vector as Vec
import           Lens.Micro.Platform ( (.=) )

import           Network.Mattermost.Types

import           Matterhorn.State.ListWindow
import           Matterhorn.Themes
import           Matterhorn.Types


-- | Show the user list window with the given search scope, and issue a
-- request to gather the first search results.
enterThemeListMode :: TeamId -> MH ()
enterThemeListMode :: TeamId -> MH ()
enterThemeListMode TeamId
tId =
    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 InternalTheme ())
tsThemeListWindow)
        Mode
ThemeListWindow () (TeamId -> InternalTheme -> MH Bool
setInternalTheme TeamId
tId) () -> Session -> Text -> IO (Vector InternalTheme)
getThemesMatching

-- | Move the selection up in the user list window by one user.
themeListSelectUp :: TeamId -> MH ()
themeListSelectUp :: TeamId -> MH ()
themeListSelectUp TeamId
tId = TeamId
-> (List Name InternalTheme -> List Name InternalTheme) -> MH ()
themeListMove 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 user list window by one user.
themeListSelectDown :: TeamId -> MH ()
themeListSelectDown :: TeamId -> MH ()
themeListSelectDown TeamId
tId = TeamId
-> (List Name InternalTheme -> List Name InternalTheme) -> MH ()
themeListMove 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 user list window by a page of users
-- (themeListPageSize).
themeListPageUp :: TeamId -> MH ()
themeListPageUp :: TeamId -> MH ()
themeListPageUp TeamId
tId = TeamId
-> (List Name InternalTheme -> List Name InternalTheme) -> MH ()
themeListMove 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
themeListPageSize))

-- | Move the selection down in the user list window by a page of users
-- (themeListPageSize).
themeListPageDown :: TeamId -> MH ()
themeListPageDown :: TeamId -> MH ()
themeListPageDown TeamId
tId = TeamId
-> (List Name InternalTheme -> List Name InternalTheme) -> MH ()
themeListMove TeamId
tId (forall (t :: * -> *) n e.
(Foldable t, Splittable t) =>
Int -> GenericList n t e -> GenericList n t e
L.listMoveBy Int
themeListPageSize)

-- | Transform the user 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.
themeListMove :: TeamId -> (L.List Name InternalTheme -> L.List Name InternalTheme) -> MH ()
themeListMove :: TeamId
-> (List Name InternalTheme -> List Name InternalTheme) -> MH ()
themeListMove 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 InternalTheme ())
tsThemeListWindow)

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

getThemesMatching :: ()
                  -> Session
                  -> Text
                  -> IO (Vec.Vector InternalTheme)
getThemesMatching :: () -> Session -> Text -> IO (Vector InternalTheme)
getThemesMatching ()
_ Session
_ Text
searchString = do
    let matching :: [InternalTheme]
matching = forall a. (a -> Bool) -> [a] -> [a]
filter InternalTheme -> Bool
matches [InternalTheme]
internalThemes
        search :: Text
search = Text -> Text
T.toLower Text
searchString
        matches :: InternalTheme -> Bool
matches InternalTheme
t = Text
search Text -> Text -> Bool
`T.isInfixOf` Text -> Text
T.toLower (InternalTheme -> Text
internalThemeName InternalTheme
t) Bool -> Bool -> Bool
||
                    Text
search Text -> Text -> Bool
`T.isInfixOf` Text -> Text
T.toLower (InternalTheme -> Text
internalThemeDesc InternalTheme
t)
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. [a] -> Vector a
Vec.fromList [InternalTheme]
matching

setInternalTheme :: TeamId -> InternalTheme -> MH Bool
setInternalTheme :: TeamId -> InternalTheme -> MH Bool
setInternalTheme TeamId
tId InternalTheme
t = do
    TeamId -> Text -> MH ()
setTheme TeamId
tId forall a b. (a -> b) -> a -> b
$ InternalTheme -> Text
internalThemeName InternalTheme
t
    forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False

setTheme :: TeamId -> Text -> MH ()
setTheme :: TeamId -> Text -> MH ()
setTheme TeamId
tId Text
name =
    case Text -> Maybe InternalTheme
lookupTheme Text
name of
        Maybe InternalTheme
Nothing -> TeamId -> MH ()
enterThemeListMode TeamId
tId
        Just InternalTheme
it -> do
            forall a. EventM Name ChatState a -> MH a
mh forall n s. Ord n => EventM n s ()
invalidateCache
            Lens' ChatState ChatResources
csResourcesforall b c a. (b -> c) -> (a -> b) -> a -> c
.Lens' ChatResources AttrMap
crTheme forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= (Theme -> AttrMap
themeToAttrMap forall a b. (a -> b) -> a -> b
$ InternalTheme -> Theme
internalTheme InternalTheme
it)