You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: main_loop.rs
    path of file: ./repos/bracket-lib/bracket-terminal/src/hal/crossterm_be
    
    the code of the file until where you have to start completion: use super::keycode_to_key;
use super::{virtual_key_code_to_scan, BACKEND};
use crate::consoles::Console;
use crate::prelude::{
    to_char, BEvent, BTerm, GameState, SimpleConsole, SparseConsole, VirtualKeyCode,
    BACKEND_INTERNAL,
};
use crate::{clear_input_state, BResult};
use bracket_color::prelude::*;
use crossterm::event::{poll, read, Event};
use crossterm::execute;
use crossterm::style::Print;
use crossterm::terminal::SetSize;
use crossterm::{cursor, queue};
use std::collections::HashSet;
use std::io::{stdout, Write};
use std::time::Duration;
use std::time::Instant;

pub fn main_loop<GS: GameState>(mut bterm: BTerm, mut gamestate: GS) -> BResult<()> {
    let now = Instant::now();
    let mut prev_seconds = now.elapsed().as_secs();
    let mut prev_ms = now.elapsed().as_millis();
    let mut frames = 0;

    // Panic handler to reset terminal
    ctrlc::set_handler(move || {
        reset_terminal();
    });

    let mut key_map: HashSet<crossterm::event::KeyCode> = HashSet::new();
    let mut keys_this_frame: HashSet<crossterm::event::KeyCode> = HashSet::new();
    let mut output_buffer: Option<Vec<OutputBuffer>> = None;

    crossterm::terminal::enable_raw_mode().expect("Raw mode failed");

    'main: while !bterm.quitting {
        let now_seconds = now.elapsed().as_secs();
        frames += 1;

        if now_seconds > prev_seconds {
            bterm.fps = frames as f32 / (now_seconds - prev_seconds) as f32;
            frames = 0;
            prev_seconds = now_seconds;
        }

        let now_ms = now.elapsed().as_millis();
        if now_ms > prev_ms {
            bterm.frame_time_ms = (now_ms - prev_ms) as f32;
            prev_ms = now_ms;
        }

        // Input
        clear_input_state(&mut bterm);

        // Input handler goes here
        keys_this_frame.clear();
        while poll(Duration::from_millis(0))? {
            match read().expect("Uh oh") {
                Event::Mouse(event) => {
                    //println!("{:?}", event);
                    // Button capture goes here
                    // Mouse doesn't seem to support cursor position? That's going to cause issues.
                    match event.kind {
                        crossterm::event::MouseEventKind::Down(button) => {
                            bterm.left_click = true;
                            bterm.mouse_pos = (event.column as i32, event.row as i32);
                            bterm.on_mouse_position(event.column as f64, event.row as f64);
                            bterm.on_mouse_button(button as usize, true);
                        }
                        crossterm::event::MouseEventKind::Up(button) => {
                            bterm.on_mouse_button(button as usize, false);
                        }
                        crossterm::event::MouseEventKind::Drag(..) => {
                            bte
    
fn full_redraw() -> BResult<Vec<OutputBuffer>> {
    let be = BACKEND.lock();
    let mut bi = BACKEND_INTERNAL.lock();

    let (width, height) = crossterm::terminal::size()?;
    let mut buffer = vec![OutputBuffer::default(); (height as usize + 2) * width as usize];

    // Tell each console to draw itself
    for cons in &mut bi.consoles {
        let cons_any = cons.console.as_any_mut();
        if let Some(st) = cons_any.downcast_mut::<SimpleConsole>() {
            if st.is_dirty {
                st.clear_dirty();
                let mut idx = 0;
                let mut last_bg = RGBA::new();
                let mut last_fg = RGBA::new();
                for y in 0..u32::min(st.height, height as u32) {
                    queue!(
                        stdout(),
                        cursor::MoveTo(0, st.height as u16 - (y as u16 + 1))
                    )
                    .expect("Command fail");
                    let mut buf_idx = (st.height as u16 - (y as u16 + 1)) as usize * width as usize;
                    for x in 0..u32::min(st.width, width as u32) {
                        let t = &st.tiles[idx];
                        if t.fg != last_fg {
                            queue!(
                                stdout(),
                                crossterm::style::SetForegroundColor(
                                    crossterm::style::Color::Rgb {
                                        r: (t.fg.r * 255.0) as u8,
                                        g: (t.fg.g * 255.0) as u8,
                                        b: (t.fg.b * 255.0) as u8,
                                    }
                                )
                            )
                            .expect("Command fail");
                            last_fg = t.fg;
                        }
                        if t.bg != last_bg {
                            queue!(
                                stdout(),
                                crossterm::style::SetBackgroundColor(
                                    crossterm::style::Color::Rgb {
                                        r: (t.bg.r * 255.0) as u8,
                                        g: (t.bg.g * 255.0) as u8,
                                        b: (t.bg.b * 255.0) as u8,
                                    }
                                )
                            )
                            .expect("Command fail");
                            last_bg = t.bg;
                        }
                        queue!(stdout(), Print(to_char(t.glyph as u8))).expect("Command fail");
                        buffer[buf_idx].glyph = to_char(t.glyph as u8);
                        buffer[buf_idx].fg = t.fg;
                        buffer[buf_idx].bg = t.bg;
                        idx += 1;
                        buf_idx += 1;
                    }
                }
            }
        } else if let Some(st) = cons_any.downcast_mut::<SparseConsole>() {
            if st.is_dirty {
                st.clear_dirty();
                for t in st.tiles.iter() {
                    let x = t.idx as u32 % st.width;
                    let y = t.idx as u32 / st.width;
                    queue!(
                        stdout(),
                        cursor::MoveTo(x as u16, st.height as u16 - (y as u16 + 1) as u16)
                    )
                    .expect("Command fail");
                    queue!(
                        stdout(),
                        crossterm::style::SetForegroundColor(crossterm::style::Color::Rgb {
                            r: (t.fg.r * 255.0) as u8,
                            g: (t.fg.g * 255.0) as u8,
                            b: (t.fg.b * 255.0) as u8,
                        })
                    )
                    .expect("Command fail");
                    queue!(
                        stdout(),
                        crossterm::style::SetBackgroundColor(crossterm::style::Color::Rgb {
                            r: (t.bg.r * 255.0) as u8,
                            g: (t.bg.g * 255.0) as u8,
                            b: (t.bg.b * 255.0) as u8,
                        })
                    )
                    .expect("Command fail");
                    queue!(stdout(), Print(to_char(t.glyph as u8))).expect("Command fail");
                    let buf_idx =
                        (((st.height as u16 - (y as u16 + 1)) * height) + x as u16) as usize;
                    buffer[buf_idx].glyph = to_char(t.glyph as u8);
                    buffer[buf_idx].fg = t.fg;
                    buffer[buf_idx].bg = t.bg;
                }
            }
        }
    }

    //bterm.backend.platform.window.refresh();
    stdout().flush().expect("Command fail");

    Ok(buffer)
}