-- | Support for more(1) buffering
module Lambdabot.Plugin.Core.More (morePlugin) where

import Lambdabot.Bot
import Lambdabot.Monad
import Lambdabot.Plugin

import Control.Monad.Trans

type MoreState = GlobalPrivate () [String]
type More = ModuleT MoreState LB

-- the @more state is handled centrally
morePlugin :: Module (GlobalPrivate () [String])
morePlugin = newModule
    { moduleDefState = return $ mkGlobalPrivate 20 ()
    , moduleInit = registerOutputFilter moreFilter
        -- TODO: improve output filter system...
        -- currently, @more output will bypass any filters in the
        -- chain after 'moreFilter'

    , moduleCmds = return
        [ (command "more")
            { help = say "@more. Return more output from the bot buffer."
            , process = \_ -> do
                target <- getTarget
                morestate <- readPS target
                -- TODO: test theory that we can just "say" morestate;
                --       it should end up going through the moreFilter as needed
                case morestate of
                    Nothing -> return ()
                    Just ls -> lift (moreFilter target ls)
                        >>= mapM_ (lb . ircPrivmsg' target)
            }
        ]
    }

moreFilter :: Nick -> [String] -> More [String]
moreFilter target msglines = do
    let (morelines, thislines) = case drop (maxLines+2) msglines of
          [] -> ([],msglines)
          _  -> (drop maxLines msglines, take maxLines msglines)
    writePS target $ if null morelines then Nothing else Just morelines
    return $ thislines ++ if null morelines
                          then []
                          else ['[':shows (length morelines) " @more lines]"]

    where maxLines = 5 -- arbitrary, really