import util;
import game;
import core.stdc.signal;
import std.c.stdlib;

abstract class Output
{
	void command(char c);
	void flush();
}

class NilOutput : Output
{
	override void command(char c) {}
	override void flush() {}
}

class StdOutput : Output
{
	override void command(char c)
	{
		write(c);
		stdout.flush();
	}
	override void flush() {}
}

// TODO: clean it up.
__gshared Output g_output;

class GuardedOutput : StdOutput
{
	// Handle SIGINT: force abort and exit.
	static this()
	{
		signal(SIGINT, &sigint);
	}

	extern(C) static void sigint(int)
	{
		if(g_output !is null)
			g_output.flush();
		else {
			write("A");
			stdout.flush();
		}
		exit(0);
	}

	Game g;
	this(Game ini) { this.g = ini.clone(); ideal_log ~= g.score_if_abort_now; g_output = this; }

	string log;
	long[] score_log;
	long[] ideal_log;

	override void command(char c)
	{
		g.command(c);
		log ~= c;
		score_log ~= g.score;
		ideal_log ~= g.score_if_abort_now;
	}
	override void flush()
	{
		Tuple!(long, int, int) cand;
		cand[0] = long.min;
		foreach(int i, long s; score_log)
			if(cand[0] < s)	
				cand = tuple(s,i,0);
		foreach(int i, long s; ideal_log)
			if(cand[0] < s)	
				cand = tuple(s,i,1);
		if(cand[2]==0)
			writeln(log[0..cand[1]+1]);
		else
			writeln(log[0..cand[1]]~"A");
		stdout.flush();
	}
}
