import std::io;
import std::io::file;
import std::io::path;
import std::os::env;
import std::core::mem::allocator;
import std::collections::object;
import std::collections::list;


alias StrList = list::List{String};

fn Path? String.to_expanded_path(&str, Allocator allocator)
{
	@pool() {
		StrList l;
		l.tinit();
		Path str_path = str.to_tpath()!;
	
		l.push(str_path.basename());
		Path? p = str_path.parent();
		while (true) {
			Path? x;
			if (try p) {
				String n = p.basename();
		
				// env variable
				if (n.starts_with("$")) {
					l.push(env::tget_var(n[1..]))!;
				} else {
					l.push(n);
				}
				
				x = p.parent();
			} else {
				break;
			}
			p = x;
		}

		Path path = path::temp("")!;
		foreach_r (idx, s: l) {
			path = path.tappend(s)!;
		}

		return path::new(allocator, path.str_view(), path.env);
	};
}

fn StrList get_qemu_cmdline(Allocator allocator, Object* conf)
{
	// parse the disk path
	String disk = conf.get_string("disk")!!;
	Path disk_path = disk.to_expanded_path(mem)!!;
	defer disk_path.free();

	// compose the command line for the vm
	StrList cmd;
	cmd.init(allocator);

	// first the executable
	cmd.push(conf.get_string("qemu"))!!;
	// then the drive
	cmd.push("-drive");
	cmd.push(string::format(allocator, "file=%s", disk_path.str_view()));
	//cmd.push(string::format(allocator, "file=%s,format=%s", disk_path.str_view(), disk_path.extension()))!!;
	// memory
	cmd.push("-m");
	cmd.push(conf.get_string("memory"))!!;
	// processors
	cmd.push("-smp");
	cmd.push(conf.get_string("processors") ?? "1");
	// then all the parameters
	Object* parameters = conf.get("parameters")!!;
	for (usz i = 0; i < parameters.get_len(); i++) {
		Object* p = parameters.get_at(i);
		if (p.is_string()) {
			cmd.push(string::format(allocator, "-%s", p.s));
		} else if (p.is_indexable()) {
			cmd.push(string::format(allocator, "-%s", p.get_string_at(0)))!!;
			cmd.push(p.get_string_at(1))!!;
		}
	}

	return cmd;
}
