drawNotify :: Quake ()
drawNotify = do
    console <- use $ globals.gCon
    vidDefWidth <- use $ globals.gVidDef.vdWidth
    cls' <- use $ globals.gCls

    v <- draw cls' console 0 ((console^.cCurrent) - Constants.numConTimes + 1) (console^.cCurrent)

    v' <- if (cls'^.csKeyDest) == Constants.keyMessage
            then do
              chatTeam' <- use $ globals.gChatTeam
              skip <- if chatTeam'
                        then do
                          drawString 8 v "say_team:"
                          return 11
                        else do
                          drawString 8 v "say:"
                          return 5

              s <- use $ globals.gChatBuffer
              chatLen <- use $ globals.gChatBufferLen
              let s' = if chatLen > (vidDefWidth `shiftR` 3) - (skip + 1)
                         then B.drop (chatLen - ((vidDefWidth `shiftR` 3) - (skip + 1))) s 
                         else s
              drawChat s' skip v 0 (B.length s')
              return (v + 8)
            else
              return v

    when (v' /= 0) $ do
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (vidDefWidth - 1) v'

  where draw :: ClientStaticT -> ConsoleT -> Int -> Int -> Int -> Quake Int
        draw cls' console v idx maxIdx
          | idx > maxIdx = return v
          | idx < 0 = draw cls' console v (idx + 1) maxIdx
          | otherwise = do
              let time = truncate ((console^.cTimes) UV.! (idx `mod` Constants.numConTimes)) :: Int

              if time == 0
                then draw cls' console v (idx + 1) maxIdx
                else do
                  let time' = (cls'^.csRealTime) - time
                  conNotifyTimeValue <- liftM (^.cvValue) conNotifyTimeCVar
                  if time' > truncate (conNotifyTimeValue * 1000)
                    then draw cls' console v (idx + 1) maxIdx
                    else do
                      let text = (idx `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                      drawText console v text 0 (console^.cLineWidth)
                      draw cls' console (v + 8) (idx + 1) maxIdx

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console v text idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              c <- io $ MSV.read (console^.cText) (text + idx)
              (renderer^.rRefExport.reDrawChar) ((idx + 1) `shiftL` 3) v (ord c)
              drawText console v text (idx + 1) maxIdx

        drawChat :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawChat s skip v idx maxIdx
          | idx >= maxIdx = do
              realTime <- use $ globals.gCls.csRealTime
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (10 + ((realTime `shiftR` 8) .&. 1))
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (ord $ s `BC.index` idx)
              drawChat s skip v (idx + 1) maxIdx
              

{-
- ================ Con_DrawInput
- 
- The input line scrolls horizontally if typing goes beyond the right edge
- ================
-}
drawNotify :: Quake ()
drawNotify = do
    console <- use $ globals.gCon
    vidDefWidth <- use $ globals.gVidDef.vdWidth
    cls' <- use $ globals.gCls

    v <- draw cls' console 0 ((console^.cCurrent) - Constants.numConTimes + 1) (console^.cCurrent)

    v' <- if (cls'^.csKeyDest) == Constants.keyMessage
            then do
              chatTeam' <- use $ globals.gChatTeam
              skip <- if chatTeam'
                        then do
                          drawString 8 v "say_team:"
                          return 11
                        else do
                          drawString 8 v "say:"
                          return 5

              s <- use $ globals.gChatBuffer
              chatLen <- use $ globals.gChatBufferLen
              let s' = if chatLen > (vidDefWidth `shiftR` 3) - (skip + 1)
                         then B.drop (chatLen - ((vidDefWidth `shiftR` 3) - (skip + 1))) s 
                         else s
              drawChat s' skip v 0 (B.length s')
              return (v + 8)
            else
              return v

    when (v' /= 0) $ do
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (vidDefWidth - 1) v'

  where draw :: ClientStaticT -> ConsoleT -> Int -> Int -> Int -> Quake Int
        draw cls' console v idx maxIdx
          | idx > maxIdx = return v
          | idx < 0 = draw cls' console v (idx + 1) maxIdx
          | otherwise = do
              let time = truncate ((console^.cTimes) UV.! (idx `mod` Constants.numConTimes)) :: Int

              if time == 0
                then draw cls' console v (idx + 1) maxIdx
                else do
                  let time' = (cls'^.csRealTime) - time
                  conNotifyTimeValue <- liftM (^.cvValue) conNotifyTimeCVar
                  if time' > truncate (conNotifyTimeValue * 1000)
                    then draw cls' console v (idx + 1) maxIdx
                    else do
                      let text = (idx `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                      drawText console v text 0 (console^.cLineWidth)
                      draw cls' console (v + 8) (idx + 1) maxIdx

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console v text idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              c <- io $ MSV.read (console^.cText) (text + idx)
              (renderer^.rRefExport.reDrawChar) ((idx + 1) `shiftL` 3) v (ord c)
              drawText console v text (idx + 1) maxIdx

        drawChat :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawChat s skip v idx maxIdx
          | idx >= maxIdx = do
              realTime <- use $ globals.gCls.csRealTime
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (10 + ((realTime `shiftR` 8) .&. 1))
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (ord $ s `BC.index` idx)
              drawChat s skip v (idx + 1) maxIdx
              

{-
- ================ Con_DrawInput
- 
- The input line scrolls horizontally if typing goes beyond the right edge
- ================
-}
drawNotify = do
    console <- use $ globals.gCon
    vidDefWidth <- use $ globals.gVidDef.vdWidth
    cls' <- use $ globals.gCls

    v <- draw cls' console 0 ((console^.cCurrent) - Constants.numConTimes + 1) (console^.cCurrent)

    v' <- if (cls'^.csKeyDest) == Constants.keyMessage
            then do
              chatTeam' <- use $ globals.gChatTeam
              skip <- if chatTeam'
                        then do
                          drawString 8 v "say_team:"
                          return 11
                        else do
                          drawString 8 v "say:"
                          return 5

              s <- use $ globals.gChatBuffer
              chatLen <- use $ globals.gChatBufferLen
              let s' = if chatLen > (vidDefWidth `shiftR` 3) - (skip + 1)
                         then B.drop (chatLen - ((vidDefWidth `shiftR` 3) - (skip + 1))) s 
                         else s
              drawChat s' skip v 0 (B.length s')
              return (v + 8)
            else
              return v

    when (v' /= 0) $ do
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (vidDefWidth - 1) v'

  where draw :: ClientStaticT -> ConsoleT -> Int -> Int -> Int -> Quake Int
        draw cls' console v idx maxIdx
          | idx > maxIdx = return v
          | idx < 0 = draw cls' console v (idx + 1) maxIdx
          | otherwise = do
              let time = truncate ((console^.cTimes) UV.! (idx `mod` Constants.numConTimes)) :: Int

              if time == 0
                then draw cls' console v (idx + 1) maxIdx
                else do
                  let time' = (cls'^.csRealTime) - time
                  conNotifyTimeValue <- liftM (^.cvValue) conNotifyTimeCVar
                  if time' > truncate (conNotifyTimeValue * 1000)
                    then draw cls' console v (idx + 1) maxIdx
                    else do
                      let text = (idx `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                      drawText console v text 0 (console^.cLineWidth)
                      draw cls' console (v + 8) (idx + 1) maxIdx

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console v text idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              c <- io $ MSV.read (console^.cText) (text + idx)
              (renderer^.rRefExport.reDrawChar) ((idx + 1) `shiftL` 3) v (ord c)
              drawText console v text (idx + 1) maxIdx

        drawChat :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawChat s skip v idx maxIdx
          | idx >= maxIdx = do
              realTime <- use $ globals.gCls.csRealTime
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (10 + ((realTime `shiftR` 8) .&. 1))
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((idx + skip) `shiftL` 3) v (ord $ s `BC.index` idx)
              drawChat s skip v (idx + 1) maxIdx
              

{-
- ================ Con_DrawInput
- 
- The input line scrolls horizontally if typing goes beyond the right edge
- ================
-}