packages feed

matsuri-0.0.3: Buffers.hs

-- | Buffers.hs
-- A module with defenition of buffer structures (structures which
-- contain text and info about opened rooms and privates).

module Buffers where

import Utils

import Network.XMPP
import Network.XMPP.MUC
import Control.Concurrent (ThreadId)
import Graphics.Vty (Event)
import qualified Data.Map as M
import Data.List
import Data.List.Split
import Data.Maybe


type Buffers = M.Map Key Buffer
type Key = String
data Buffer = BufAccount Account
            | BufChat Chat
            | BufGroup Group
            | BufRoom Room
            | BufUnknown -- ^ fallback buffer

-- show instances
instance Show Buffer where
    show (BufAccount acc) =
      case connection acc of
        OK _ _ -> c:" [o] "++accName acc
        NoConnection -> c:" [_] "++accName acc
        Trying -> c:" [!] "++accName acc
      where c = if accCollapsed acc then '+' else '-'
    show (BufGroup grp) = coll++name (grpName grp)
      where coll = if grpCollapsed grp then "  +++ "
                                       else "  --- "
    show (BufChat chat) = "  "++(show $ status chat)++
                          " "++(itemJid $ item chat)
    show (BufRoom room)
      = " "++mark occ++" "++name (roomName room)
      where
        mark (Just occ') = roomBrackets occ' 'C' True
        mark _           = " [C]"
        occ = M.lookup (roomNick room) (roomOccupants room)

name = drop 1 . dropWhile (/='|')

instance Show Status where
    show (Status StatusOnline  _) = "[o]"
    show (Status StatusAway    _) = "[a]"
    show (Status StatusChat    _) = "[c]"
    show (Status StatusDND     _) = "[d]"
    show (Status StatusXA      _) = "[n]"
    show (Status StatusOffline _) = "[_]"

instance Show Occupant where
    show occ = br ++ nick ++ jid
      where
        br = roomBrackets occ 'o' False
        nick | null br   = occNick occ
             | otherwise = " " ++ occNick occ
        jid = maybe "" (\j -> " ["++j++"]") (occJid occ)
-- | Draw room brackets (<>, {} or []).
roomBrackets :: Occupant
             -> Char -- ^ char between the brackets (C, o, a, etc)
             -> Bool -- ^ draw or not default status ([o])
             -> String
roomBrackets occ s always =
    role++(aff (occAffiliation occ))
  where
    role = role' (occRole occ)
    role' RModerator    = "+"
    role' RVisitor      = "-"
    role' _ | always    = " "
            | otherwise = ""
    ---
    aff AOwner = '<':s:'>':[]
    aff AAdmin = '{':s:'}':[]
    aff _ | always || (not $ null role) = '[':s:']':[]
          | otherwise                 = ""
-- | Draw all room occupants (like /names in irssi).
showOccupants :: [Occupant] -> Int -> String
showOccupants occs w =
    "Names:\n"++
    (intercalate "\n" $ map concat $ chunk row occs')
  where
    occs' = map drawOcc occs
    drawOcc occ
      = (take' (len-1) ' ' $ roomBrackets occ 'o' True
                           ++ " " ++ occNick occ)
        ++ " "
    row = (w - offset) `div` len
    len = 23
    offset = 9

-- GDAT

data Account = Account
    { accName :: String
    , username :: String
    , server :: String
    , password :: String
    , resource :: String
    , priority :: Integer
    , defaultNick :: String
    , connection :: Connection
    , accCollapsed :: Bool
    , accContents :: [Content]
    }

data Connection = OK TCPConnection ThreadId
                | NoConnection
                | Trying

data Group = Group
    { grpName :: String
    , grpCollapsed :: Bool
    , grpItems :: [String]
    }

data Chat = Chat
    { item :: RosterItem
    , status :: Status
    , chatName :: String
    , chatContents :: [Content]
    }

data Room = Room
    { roomName :: String
    , roomContents :: [Content]
    , roomNick :: String
    , roomSubject :: String
    , roomOccupants :: M.Map String Occupant
    }

-- | New contents goes at top for more eaiser insert.
data Content = Msg String
             | MyMsg String
             | HistoryMsg String
             | InfoMsg String

-- | Event which pushed/popped from/to MVar.
data MEvent = VtyEvent Event
            | InsBuffer Key Buffer
            | NewMsg Key Content
            | NewRoomMsg Key (Maybe String, String, Maybe String)
            | NewStatus Key Status
            | RoomPresence REvent String Occupant Content

-- | Room presence type.
data REvent = Join
            | Leave


insElem :: Key -> Buffer -> Buffers -> Buffers
insElem k = M.insert k

getAcc :: Key -> Buffers -> Account
getAcc k buffers =
    case M.lookup k buffers of
      Just (BufAccount acc) -> acc

getBuf :: Key -> Buffers -> Buffer
getBuf k buffers =
    case M.lookup k buffers of
      Just buf -> buf
      _ -> BufUnknown

isBuf :: Key -> Buffers -> Bool
isBuf k = isJust . M.lookup k

-- | Kill room should run leaveGroupchat
killBuffers :: String -> Buffers -> Buffers
killBuffers startswith =
    M.filterWithKey (\k _ -> not $ startswith `isPrefixOf` k)