package AA::UI;

sub new($$) {
	my ($class, $name) = @_;
	if ($name eq "") {
		return AA::UI::GTK->new;
	} elsif ($name =~ /\.pdf$/) {
		return AA::UI::PDF->new($name);
	} elsif ($name =~ /\.png$/) {
		return AA::UI::PNG->new($name);
	}
}

package AA::UI::GTK;

@ISA = ('AA::UI');

sub new($) {
	my ($class) = @_;
	my $ui = {
	};
	return bless($ui, $class);
}

my $u_scenario;
my $u_scene;

my $window;
my $cairo;
my $area;
my $pixmap;
my $timer;
my $stopped = 1;
my $fullscreen = 0;
my ($lastw, $lasth, $lastd) = (-1, -1, -1);
my ($pixw, $pixh) = (-1, -1);

sub draw($) {
	my ($force) = @_;
	my $win = $area->window;
	my $wgc = Gtk2::Gdk::GC->new($win);
	my $alloc = $area->allocation;
	my $w = $alloc->width;
	my $h = $alloc->height;
	my $d = $win->get_depth;
	# print "Area $w x $h x $d, xx=$xx\n";

	if (!defined($pixmap) || $lastw != $w || $lasth != $h || $lastd != $d) {
		($lastw, $lasth, $lastd) = ($w, $h, $d);
		if ($w/$h >= 4/3) {
			$pixh = $h;
			$pixw = int($h/3*4);
		} else {
			$pixw = $w;
			$pixh = int($w/4*3);
		}
		print "Resized to ${w}x${h}, pixmap size ${pixw}x${pixh}\n";

		$pixmap = Gtk2::Gdk::Pixmap->new($win, $pixw, $pixh, $d);
		$cairo = Gtk2::Gdk::Cairo::Context->create($pixmap);
		$cairo->select_font_face('URW Palladio L', 'normal', 'normal');
		my $scale = $pixw/1024;
		$cairo->scale($scale, $scale);
	}

	if ($force) {
		$wgc->set_rgb_background(0);
		$wgc->set_rgb_foreground(0);
		$win->draw_rectangle($wgc, 1, 0, 0, $w, $h);
	}

	$cairo->rectangle(0, 0, 1024, 768);
	$cairo->set_source_rgb(0, 0, 0);
	$cairo->fill;

	AA->calculate;
	AA->draw($cairo);

	$win->draw_drawable($wgc, $pixmap, 0, 0, 0, 0, $pixw, $pixh);
}

sub step() {
	AA::Anim->step;
	draw(0);
}

sub prepare() {
	$window = Gtk2::Window->new ('toplevel');
	$area = Gtk2::DrawingArea->new();
	$area->signal_connect("expose-event" => sub {
		draw(1);
		if (!defined $timer) {
			$timer = Glib::Timeout->add(30, sub { $stopped || step(); return 1; });
		}
	});
	$area->set_flags('can-focus');
	# $area->add_events('key-press-mask');
	$area->signal_connect('key-press-event' => sub {
		my ($w, $evt) = @_;
		my $k = Gtk2::Gdk::keyval_name(0, $evt->keyval);
		print "Pressed key $k\n";
		if ($k eq "Escape") {
			Gtk2->main_quit;
		} elsif ($k eq "space") {
			$stopped = !$stopped;
		} elsif ($k eq "f") {
			if ($fullscreen = !$fullscreen) {
				$window->fullscreen;
			} else {
				$window->unfullscreen;
			}
		} elsif ($k eq "Right") {
			if ($u_scene+1 < @$u_scenario) {
				$u_scene++;
				&{$u_scenario->[$u_scene]};
				draw(0);
			}
		}
	});

	$window->signal_connect ("delete-event" => sub { Gtk2->main_quit });
	$window->set_title("Brum");
	$window->set_wmclass("brum", "Brum");
	$window->set_default_size(640, 480);
	$window->add ($area);
	$window->show_all;
}

sub RunScenario($$$) {
	my ($ui, $scenario, $live) = @_;
	$u_scenario = $scenario;
	$u_scene = 0;
	&{$scenario->[0]};
	prepare();
	Gtk2->main;
}

package AA::UI::PDF;

@ISA = ('AA::UI');

sub new($$) {
	my ($class, $name) = @_;
	my $ui = { };
	$ui->{SURF} = Cairo::PdfSurface->create($name, 512, 384) or die "Unable to create PDF surface $name\n";
	$ui->{CAIRO} = Cairo::Context->create($ui->{SURF});
	$ui->{CAIRO}->scale(.5, .5);
	return bless($ui, $class);
}

sub RunScenario($$$) {
	my ($ui, $scenario) = @_;
	my $page = 0;
	foreach my $s (@$scenario) {
		$page++;
		print "### Page $page ###\n";
		&$s();
		AA->calculate;
		AA->draw($ui->{CAIRO});
		$ui->{CAIRO}->show_page;
	}
}

package AA::UI::PNG;

@ISA = ('AA::UI');

sub new($$) {
	my ($class, $name) = @_;
	my $ui = { };
	$ui->{NAME} = $name;
	$ui->{SURF} = Cairo::ImageSurface->create('argb32', 1024, 768) or die "Unable to create image surface $name\n";
	$ui->{CAIRO} = Cairo::Context->create($ui->{SURF});
	return bless($ui, $class);
}

sub RunScenario($$$) {
	my ($ui, $scenario) = @_;
	my $cairo = $ui->{CAIRO};
	my $page = 0;
	foreach my $s (@$scenario) {
		$page++;
		print "### Page $page ###\n";
		&$s();
		AA->calculate;
		AA->draw($cairo);
		$cairo->show_page;
		my $name = sprintf($ui->{NAME}, $page);
		$ui->{SURF}->write_to_png($name) or die "Unable to write to $name\n";
	}
}

1;
