drawConsole :: Float -> Quake ()
drawConsole frac = do
    vidDef' <- use $ globals.gVidDef

    let width = vidDef'^.vdWidth
        height = vidDef'^.vdHeight
        tmpLinesNum = truncate ((fromIntegral height) * frac)

    unless (tmpLinesNum <= 0) $ do
      let linesNum = if tmpLinesNum > height
                       then height
                       else tmpLinesNum

      -- draw the background
      Just renderer <- use $ globals.gRenderer
      (renderer^.rRefExport.reDrawStretchPic) 0 (-height + linesNum) width height "conback"
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (width - 1) (linesNum - 1)

      let version = BC.pack (printf "v%4.2f" Constants.version)
      drawVersion version width linesNum 0 5

      -- draw the text
      globals.gCon.cVisLines .= linesNum
      console <- use $ globals.gCon

      (rows, y) <- do
        let rows = (linesNum - 22) `shiftR` 3 -- rows of text to draw
            y = linesNum - 30

        -- draw from the bottom up
        if (console^.cDisplay) /= (console^.cCurrent)
          then do
            -- draw arrows to show the buffer is backscrolled
            drawArrows 0 (console^.cLineWidth) y
            return (rows - 1, y - 8)
          else
            return (rows, y)

      let row = console^.cDisplay
      drawText console row y 0 rows

      download <- use $ globals.gCls.csDownload

      when (isJust download) $ do
        io (putStrLn "Console.drawConsole") >> undefined -- TODO

      -- draw the input prompt, user text, and cursor if desired
      drawInput

  where drawVersion :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawVersion version width linesNum idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) (width - 44 + idx * 8) (linesNum - 12) (128 + ord (BC.index version idx))
              drawVersion version width linesNum (idx + 1) maxIdx

        drawArrows :: Int -> Int -> Int -> Quake ()
        drawArrows x maxX y
          | x >= maxX = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((x + 1) `shiftL` 3) y (ord '^')
              drawArrows (x + 4) maxX y

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console row y idx maxIdx
          | idx >= maxIdx || row < 0 || (console^.cCurrent) - row >= (console^.cTotalLines) = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              let first = (row `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                  drawChar = renderer^.rRefExport.reDrawChar
              drawLine drawChar (console^.cText) first y 0 (console^.cLineWidth)
              drawText console (row - 1) (y - 8) (idx + 1) maxIdx

        drawLine :: (Int -> Int -> Int -> Quake ()) -> MSV.IOVector Char -> Int -> Int -> Int -> Int -> Quake ()
        drawLine drawChar text first y idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              ch <- io $ text `MSV.read` (idx + first)
              drawChar ((idx + 1) `shiftL` 3) y $! (ord ch)
              drawLine drawChar text first y (idx + 1) maxIdx

{-
- ================ Con_DrawNotify ================
- 
- Draws the last few lines of output transparently over the game top
-}
drawConsole :: Float -> Quake ()
drawConsole frac = do
    vidDef' <- use $ globals.gVidDef

    let width = vidDef'^.vdWidth
        height = vidDef'^.vdHeight
        tmpLinesNum = truncate ((fromIntegral height) * frac)

    unless (tmpLinesNum <= 0) $ do
      let linesNum = if tmpLinesNum > height
                       then height
                       else tmpLinesNum

      -- draw the background
      Just renderer <- use $ globals.gRenderer
      (renderer^.rRefExport.reDrawStretchPic) 0 (-height + linesNum) width height "conback"
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (width - 1) (linesNum - 1)

      let version = BC.pack (printf "v%4.2f" Constants.version)
      drawVersion version width linesNum 0 5

      -- draw the text
      globals.gCon.cVisLines .= linesNum
      console <- use $ globals.gCon

      (rows, y) <- do
        let rows = (linesNum - 22) `shiftR` 3 -- rows of text to draw
            y = linesNum - 30

        -- draw from the bottom up
        if (console^.cDisplay) /= (console^.cCurrent)
          then do
            -- draw arrows to show the buffer is backscrolled
            drawArrows 0 (console^.cLineWidth) y
            return (rows - 1, y - 8)
          else
            return (rows, y)

      let row = console^.cDisplay
      drawText console row y 0 rows

      download <- use $ globals.gCls.csDownload

      when (isJust download) $ do
        io (putStrLn "Console.drawConsole") >> undefined -- TODO

      -- draw the input prompt, user text, and cursor if desired
      drawInput

  where drawVersion :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawVersion version width linesNum idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) (width - 44 + idx * 8) (linesNum - 12) (128 + ord (BC.index version idx))
              drawVersion version width linesNum (idx + 1) maxIdx

        drawArrows :: Int -> Int -> Int -> Quake ()
        drawArrows x maxX y
          | x >= maxX = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((x + 1) `shiftL` 3) y (ord '^')
              drawArrows (x + 4) maxX y

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console row y idx maxIdx
          | idx >= maxIdx || row < 0 || (console^.cCurrent) - row >= (console^.cTotalLines) = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              let first = (row `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                  drawChar = renderer^.rRefExport.reDrawChar
              drawLine drawChar (console^.cText) first y 0 (console^.cLineWidth)
              drawText console (row - 1) (y - 8) (idx + 1) maxIdx

        drawLine :: (Int -> Int -> Int -> Quake ()) -> MSV.IOVector Char -> Int -> Int -> Int -> Int -> Quake ()
        drawLine drawChar text first y idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              ch <- io $ text `MSV.read` (idx + first)
              drawChar ((idx + 1) `shiftL` 3) y $! (ord ch)
              drawLine drawChar text first y (idx + 1) maxIdx

{-
- ================ Con_DrawNotify ================
- 
- Draws the last few lines of output transparently over the game top
-}
drawConsole frac = do
    vidDef' <- use $ globals.gVidDef

    let width = vidDef'^.vdWidth
        height = vidDef'^.vdHeight
        tmpLinesNum = truncate ((fromIntegral height) * frac)

    unless (tmpLinesNum <= 0) $ do
      let linesNum = if tmpLinesNum > height
                       then height
                       else tmpLinesNum

      -- draw the background
      Just renderer <- use $ globals.gRenderer
      (renderer^.rRefExport.reDrawStretchPic) 0 (-height + linesNum) width height "conback"
      SCR.addDirtyPoint 0 0
      SCR.addDirtyPoint (width - 1) (linesNum - 1)

      let version = BC.pack (printf "v%4.2f" Constants.version)
      drawVersion version width linesNum 0 5

      -- draw the text
      globals.gCon.cVisLines .= linesNum
      console <- use $ globals.gCon

      (rows, y) <- do
        let rows = (linesNum - 22) `shiftR` 3 -- rows of text to draw
            y = linesNum - 30

        -- draw from the bottom up
        if (console^.cDisplay) /= (console^.cCurrent)
          then do
            -- draw arrows to show the buffer is backscrolled
            drawArrows 0 (console^.cLineWidth) y
            return (rows - 1, y - 8)
          else
            return (rows, y)

      let row = console^.cDisplay
      drawText console row y 0 rows

      download <- use $ globals.gCls.csDownload

      when (isJust download) $ do
        io (putStrLn "Console.drawConsole") >> undefined -- TODO

      -- draw the input prompt, user text, and cursor if desired
      drawInput

  where drawVersion :: B.ByteString -> Int -> Int -> Int -> Int -> Quake ()
        drawVersion version width linesNum idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) (width - 44 + idx * 8) (linesNum - 12) (128 + ord (BC.index version idx))
              drawVersion version width linesNum (idx + 1) maxIdx

        drawArrows :: Int -> Int -> Int -> Quake ()
        drawArrows x maxX y
          | x >= maxX = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              (renderer^.rRefExport.reDrawChar) ((x + 1) `shiftL` 3) y (ord '^')
              drawArrows (x + 4) maxX y

        drawText :: ConsoleT -> Int -> Int -> Int -> Int -> Quake ()
        drawText console row y idx maxIdx
          | idx >= maxIdx || row < 0 || (console^.cCurrent) - row >= (console^.cTotalLines) = return ()
          | otherwise = do
              Just renderer <- use $ globals.gRenderer
              let first = (row `mod` (console^.cTotalLines)) * (console^.cLineWidth)
                  drawChar = renderer^.rRefExport.reDrawChar
              drawLine drawChar (console^.cText) first y 0 (console^.cLineWidth)
              drawText console (row - 1) (y - 8) (idx + 1) maxIdx

        drawLine :: (Int -> Int -> Int -> Quake ()) -> MSV.IOVector Char -> Int -> Int -> Int -> Int -> Quake ()
        drawLine drawChar text first y idx maxIdx
          | idx >= maxIdx = return ()
          | otherwise = do
              ch <- io $ text `MSV.read` (idx + first)
              drawChar ((idx + 1) `shiftL` 3) y $! (ord ch)
              drawLine drawChar text first y (idx + 1) maxIdx

{-
- ================ Con_DrawNotify ================
- 
- Draws the last few lines of output transparently over the game top
-}