use std::io::{Stdout, Write, stdout};

use anyhow::{Context, Result};
use crossterm::{
    cursor::{Hide, Show},
    execute, queue,
    terminal::{
        Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode,
        enable_raw_mode,
    },
};

pub struct Terminal {
    stdout: Stdout,
}

impl Terminal {
    pub fn enter() -> Result<Self> {
        enable_raw_mode().context("failed to enable terminal raw mode")?;
        let mut stdout = stdout();
        execute!(stdout, EnterAlternateScreen, Hide, Clear(ClearType::All))
            .context("failed to enter alternate screen")?;
        Ok(Self { stdout })
    }

    pub fn stdout(&mut self) -> &mut Stdout {
        &mut self.stdout
    }
}

impl Drop for Terminal {
    fn drop(&mut self) {
        let _ = queue!(self.stdout, Show, LeaveAlternateScreen);
        let _ = self.stdout.flush();
        let _ = disable_raw_mode();
    }
}
