#![feature(yggdrasil_os, rustc_private)]

use std::{
    env,
    io::{self, stdin, stdout, BufRead, Write},
    os::{
        fd::AsRawFd,
        yggdrasil::{io::terminal::start_terminal_session, rt::io::device},
    },
    process::{Command, ExitCode},
};

fn login_readline<R: BufRead>(
    reader: &mut R,
    buf: &mut String,
    _secret: bool,
) -> Result<usize, io::Error> {
    reader.read_line(buf)
}

fn login_as(username: &str, _password: &str) -> Result<(), io::Error> {
    let mut shell = Command::new("/bin/sh").arg("-l").spawn()?;
    println!("Hello {:?}", username);
    shell.wait()?;
    Ok(())
}

fn login_attempt(erase: bool) -> Result<(), io::Error> {
    let stdin = stdin();
    let mut stdout = stdout();

    if erase {
        print!("\x1b[1;1f\x1b[2J");
        stdout.flush().ok();
    }

    let mut username = String::new();

    print!("Username: ");
    stdout.flush().ok();
    if login_readline(&mut stdin.lock(), &mut username, false)? == 0 {
        return Ok(());
    }

    login_as(username.trim(), "")
}

fn main() -> ExitCode {
    logsink::setup_logging(false);
    let args: Vec<_> = env::args().skip(1).collect();
    if args.len() != 1 {
        eprintln!("Usage: /sbin/login TTY");
        return ExitCode::FAILURE;
    }
    let terminal = args[0].as_str();

    // TODO check that `terminal` is a terminal
    log::info!("Starting a session at {}", terminal);
    if let Err(err) = unsafe { start_terminal_session(terminal) } {
        log::error!("Error: {:?}", err);
        eprintln!("Could not setup a session at {}: {:?}", terminal, err);
        return ExitCode::FAILURE;
    }

    let mut attempt_number = 0;
    loop {
        log::debug!("Login attempt {}", attempt_number);

        // "Attach" the terminal
        let group_id = std::os::yggdrasil::process::group_id();
        let mut buffer = [0; 8];
        device::device_request::<device::SetTerminalGroup>(
            stdin().as_raw_fd(),
            &mut buffer,
            &group_id,
        )
        .expect("Could not attach the terminal");

        if let Err(err) = login_attempt(attempt_number % 3 == 0) {
            eprintln!("login: {}", err);
        }
        attempt_number += 1;
    }
}
