-- |Implements Priority Queues intended to be used with the STM module.
module PupEventsPQueue (makeQueues, getThing, writeThing, PQueue) where

import Control.Concurrent.STM
import Control.Monad

-- |A simple alias so we have pretty types.
type PQueue a = [TChan a]

-- |Returns an empty PQueue with the specified number of priority levels.
makeQueues ::   Int -- ^ The number of priority levels
                -> IO (PQueue a) -- ^ The PQueue
makeQueues num = replicateM num newTChanIO

-- |Recursively tries to read each priority level until it finds something.
-- If it can't find any events it returns Nothing. Call using @atomically $
-- getThing pqueue@.
getThing :: PQueue a -- ^ The PQueue to search
            -> STM (Maybe a) -- ^ Just the item or Nothing.
getThing [] = return Nothing
getThing queues = 
    do  event <- tryReadTChan $ head queues
        case event of
            Nothing -> getThing $ tail queues
            Just e -> return (Just e)

-- |Writes the given something to the given PQueue at the specified
-- priority level. It does some checking to make sure we have a valid
-- priority level. Call using @atomically $ writeThing pqueue priority thing@.
writeThing ::   PQueue a -- ^ The PQueue to write to
                -> Int -- ^ The priority level
                -> a -- ^ The thing to write
                -> STM ()
writeThing queues priority thing =
    unless (length queues < priority && priority > 0) $
        writeTChan (queues !! priority) thing