use fmt;
use io;
use unix::tty;
use errors;
use encoding::utf8;
use bufio;

export type tui = struct {
	out: io::file,
	clear: bool,
	tq: tty::termios,
};

export type skey = enum {
	BS,
};

export type key = (skey | rune);

export fn init() (tui | tty::error | errors::error) = {
	const f = tty::open()?;
	const tq = tty::termios_query(f)?;
	tty::makeraw(&tq)?;
	//tty::noncanonical(&tq)?;
	doclear(f);
	return tui {
		out = f,
		clear = false,
		tq = tq,
	};

};

export fn read(state: *tui) (key | utf8::invalid | io::error | io::EOF) = {
	match (bufio::read_rune(state.out)?) {
	case let r: rune =>
		return r;
	case io::EOF =>
		return io::EOF;
	};

};

fn doclear(out: io::file) void = {
	fmt::fprint(out, "\x1B[2J\x1B[1;1H")!;
};

export fn clear(state: *tui) void = {
	state.clear = true;
	//fmt::fprint(out, "\x1B[2J\x1B[1;1H")!;
};

export fn finish(state: *tui) void = {
	tty::termios_restore(&state.tq);
	io::close(state.out)!;
};

export fn unraw(state: *tui) void = {
	tty::termios_restore(&state.tq);
};

export fn raw(state: *tui) (void | errors::error) = {
	const tq = tty::termios_query(state.out)?;
	tty::makeraw(&tq)?;
};
