#!/usr/bin/perl

use strict;
use lib qw(/usr/lib/libDrakX);
use standalone;
use common;
use ugtk2 qw(:create :dialogs :helpers :wrappers);
use interactive;
use bootsplash;

my $in = 'interactive'->vnew('su');

$in->do_pkgs->ensure_is_installed('ImageMagick', '/usr/bin/convert') or close_all();
$in->do_pkgs->ensure_is_installed('netpbm', '/usr/bin/jpegtopnm') or close_all();

my $window = ugtk2->new('DrakSplash');
$window->{rwindow}->signal_connect(delete_event => \&close_all);

my @image_pixbuf;
my $current_rect = [];
my $current_point;

my $preview_window = ugtk2->new('DrakSplash');
my $image_area = create_image_area();
my $scroll = create_scrolled_window($image_area);

switch_to_mode(0);

my %scale_settings = (
		      tb_x => [ 1/10, N("x coordinate of text box") ],
		      tb_y => [ 1/10, N("y coordinate of text box") ],
		      tb_w => [ 8/10, N("text box width") ],
		      tb_h => [ 8/10, N("text box height") ],
		      px => [ 2/10, N("the progress bar x coordinate\nof its upper left corner") ],
		      py => [ 7/10, N("the progress bar y coordinate\nof its upper left corner") ],
		      pw => [ 6/10, N("the width of the progress bar") ],
		      ph => [ 1/10, N("the height of the progress bar") ],
		      text_x => [ 1/10, N("x coordinate of the text") ],
		      text_y => [ 1/10, N("y coordinate of the text") ],
		      transp => [ 1/10, N("text box transparency") ],
		      ptransp => [ 1/10, N("progress box transparency") ],
		      text_size => [ 1/10, N("text size") ],
		     );

my %adj;
create_adj_widgets();
create_simple_adj_widgets();

my %theme;
set_theme('new_theme');
set_resolution([ bootsplash::get_framebuffer_resolution() ]->[0]);

my $current_mode;
my $notebook = gtksignal_connect(Gtk2::Notebook->new, switch_page => sub {
				     my (undef, undef, $mode) = @_;
				     switch_to_mode($mode);
				 });
$notebook->append_page(gtkpack__(Gtk2::VBox->new(0, 5),
				 create_scale_table('px', 'pw', 'py', 'ph', 'ptransp'),
				 gtksignal_connect(Gtk2::Button->new(N("Choose progress bar color 1")), clicked => sub { choose_color('pc1') }),
				 gtksignal_connect(Gtk2::Button->new(N("Choose progress bar color 2")), clicked => sub { choose_color('pc2') }),
				 gtksignal_connect(Gtk2::Button->new(N("Choose progress bar background")), clicked => sub { choose_color('pbg_c') }),
				 Gtk2::Label->new(N("Gradient type")), gtksignal_connect(Gtk2::ComboBoxEntry->new_with_strings([ 'vertical', 'horizontal' ], 'vertical'), changed => sub { $theme{conf}{gradient} = $_[0]->get_child->get_text }),
				 gtksignal_connect(Gtk2::Button->new(N("Choose text color")), clicked => sub { choose_color('text_color') }),
				 create_scale_table('text_x', 'text_y', 'text_size'),
				 gtksignal_connect(Gtk2::Button->new(N("Choose picture")), clicked => sub { choose_image('silentjpeg') })),
		       N("Silent bootsplash"));
$notebook->append_page(gtkpack__(Gtk2::VBox->new(0, 5),
				 create_scale_table('tb_x', 'tb_y', 'tb_w', 'tb_h', 'transp'),
				 gtksignal_connect(Gtk2::Button->new(N("Choose text zone color")), clicked => sub { choose_color('tc') }),
				 Gtk2::Label->new(N("Text color")), gtksignal_connect(Gtk2::ComboBoxEntry->new_with_strings([ 0 .. 15 ], 1), changed => sub { $theme{conf}{fgcolor} = $_[0]->get_child->get_text }),
				 Gtk2::Label->new(N("Background color")), gtksignal_connect(Gtk2::ComboBoxEntry->new_with_strings([ 0 .. 15 ], '0'), changed => sub { $theme{conf}{bgcolor} = $_[0]->get_child->get_text }),
				 gtksignal_connect(Gtk2::Button->new(N("Choose picture")), clicked => sub { choose_image('jpeg') })),
		       N("Verbose bootsplash"));
$notebook->append_page(gtkpack__(Gtk2::VBox->new(0, 5),
				 gtksignal_connect(Gtk2::CheckButton->new(N("Display logo on Console")), toggled => sub {
						       $theme{conf}{logo} = bool2yesno($_[0]->get_active);
						   })),
		       N("Console bootsplash"));

gtkadd($window->{window},
       gtkpack(Gtk2::VBox->new(0, 5),
	      gtkpack__(Gtk2::HBox->new(0, 5),
			create_packtable({ col_spacings => 10, row_spacings => 5 },
					 [ Gtk2::Label->new(N("Theme name")),
					   gtksignal_connect(Gtk2::ComboBoxEntry->new_with_strings([ bootsplash::themes_list() ], $theme{name}),
							     changed => sub { set_theme($_[0]->get_child->get_text) }) ],
					 [ Gtk2::Label->new(N("final resolution")),
					   gtksignal_connect(Gtk2::ComboBox->new_with_strings(\@bootsplash::resolutions, $theme{res}),
							     changed => sub { set_resolution($_[0]->get_text) }) ])),
	       $notebook,
	       gtkpack(Gtk2::HBox->new(0, 5),
			 gtksignal_connect(Gtk2::Button->new(N("Save theme")), clicked => \&save_theme),
			 gtksignal_connect(Gtk2::Button->new(N("Quit")), clicked => \&close_all)))),
gtkshow(gtkadd($preview_window->{window}, $scroll));

$window->{rwindow}->set_border_width(5);
$window->{rwindow}->set_position('center');
$window->{rwindow}->show_all;
$window->main;

# Should never get here
ugtk2->exit(0);

sub close_all() {
   ugtk2->exit(0);
}

sub read_theme_config() {
    my $conf = bootsplash::theme_get_config_for_resolution($theme{name}, $theme{res});
    -f $conf and $theme{conf} = bootsplash::theme_read_config_for_resolution($theme{name}, $theme{res});
    if (-f $theme{conf}{silentjpeg}) {
	load_image($theme{conf}{silentjpeg}, 0, 1);
    }
    if (-f $theme{conf}{jpeg}) {
	load_image($theme{conf}{jpeg}, 1, 1);
    }
    $theme{conf}{pc} ||= '#21459d';
    update_scale_values_from_conf();
    update_rect();
}

sub set_theme {
    my ($name) = @_;
    @image_pixbuf = ();
    $theme{name} = $name;
    read_theme_config();
}

{
    my ($old_scroll_w, $old_scroll_h);

    sub set_resolution {
	my ($res) = @_;
	$theme{res} = $res;
	($theme{res_w}, $theme{res_h}) = $theme{res} =~ /([^x]+)x([^x]+)/;
	update_scales_for_resolution();
	read_theme_config();
	$image_area->set_size_request($theme{res_w}, $theme{res_h});
	#- try not to be larger than screen size minus toolbars size
	my $w = min(Gtk2::Gdk->screen_width*0.9, $theme{res_w});
	my $h = min(Gtk2::Gdk->screen_height*0.9, $theme{res_h});
	#- do not resize and move the window again if size hasn't changed
	if ($w != $old_scroll_w || $h !=  $old_scroll_h) {
	    $scroll->set_size_request($w, $h);
	    $preview_window->shrink_topwindow;
	    $preview_window->{window}->move(0, 0);
	    ($old_scroll_w, $old_scroll_h) = ($w, $h);
	}
    }
}

sub save_theme() {
    my $_w = $in->wait_message('', N("saving Bootsplash theme..."));
    bootsplash::theme_set_image_for_resolution($theme{name}, $theme{res}, $theme{conf}{silentjpeg});
    bootsplash::theme_write_config_for_resolution($theme{name}, $theme{res}, $theme{conf});
}

sub load_image {
    my ($img, $mode, $o_no_warn) = @_;
    eval { $image_pixbuf[$mode] = Gtk2::Gdk::Pixbuf->new_from_file($img) };
    if ($@) {
        $in->ask_warn(N("Error"), N("Unable to load image file %s", $img)) unless $o_no_warn;
        return;
    }
    $image_pixbuf[$mode] = $image_pixbuf[$mode]->scale_simple($theme{res_w}, $theme{res_h}, 'hyper');
    $image_pixbuf[1-$mode] ||= $image_pixbuf[$mode];
    $image_area->queue_draw;
    1;
}

sub choose_image {
    my ($type) = @_;
    my $file_dialog = Gtk2::FileChooserDialog->new(N("choose image"), $window->{real_window}, 'open', N("Cancel") => 'cancel', N("Ok") => 'ok');
    $file_dialog->set_filename($theme{$type} || '~/');
    $file_dialog->show;
    while ($file_dialog->run eq 'ok') {
        @image_pixbuf = ();
        if (load_image(my $img = $file_dialog->get_filename, 0)) {
	    $theme{conf}{$type} = $img;
	    last;
	}
    }
    $file_dialog->destroy;
}

sub choose_color() {
    my ($var) = @_;
    my $color = gtkshow(Gtk2::ColorSelectionDialog->new(N("Color selection")));
    print "Current color $var: $theme{conf}{$var}\n";
    my @rgb = $theme{conf}{$var} =~ /^#(.{2})(.{2})(.{2})$/ ? (map { hex($_)*255 } ($1, $2, $3)) : ();
    $color->colorsel->set_current_color(gtkcolor(@rgb));
    $color->cancel_button->signal_connect(clicked => sub { $color->destroy });
    $color->ok_button->signal_connect(clicked => sub {
					  my $colour = $color->colorsel->get_current_color;
					  $theme{conf}{$var} = "#" . join('', map { sprintf("%02x", $_/256) } $colour->red, $colour->green, $colour->blue);
					  $color->destroy;
				      });
}


#- Adjustement widgets
sub create_adj_widgets() {
    $adj{$_} = Gtk2::Adjustment->new(0, 0, 0, 1, 10, 0) foreach keys %scale_settings;
    my %scale_links = (tb_x => 'tb_w', tb_y => 'tb_h', px => 'pw', py => 'ph', text_x => 'px', text_y => 'py', transp => 'transp', ptransp => 'ptransp', text_size => 'text_size' );
    while (my ($n1, $n2) = each(%scale_links)) {
	$adj{$n1}{on_change} = $adj{$n1}->signal_connect(value_changed => sub { check_scale_value($n1, $n2); apply_scale($n1) });
	$adj{$n2}{on_change} = $adj{$n2}->signal_connect(value_changed => sub { check_scale_value($n2, $n1); apply_scale($n2) });
    }
}

sub create_simple_adj_widgets() {
    $adj{$_} = Gtk2::Adjustment->new(0, 0, 0, 1, 10, 0) foreach keys %scale_settings;
    foreach my $n ('transp','ptransp', 'text_size') {
	$adj{$n}{on_change} = $adj{$n}->signal_connect(value_changed => sub { apply_scale($n) });
    }
}
sub create_scale_table {
    my @settings = @_;
    create_packtable({ col_spacings => 10, row_spacings => 5 }, map {
	my $w = Gtk2::HScale->new($adj{$_});
	$w->set_digits(0);
	[ Gtk2::Label->new($scale_settings{$_}[1]), $w ];
    } @settings);
}

sub get_scale_max {
    my ($name) = @_;
    if ($name =~ /size/) { return 100 }
    if ($name =~ /transp/) { return 255 }
    $theme{$name =~ /[xw]$/ ? "res_w" : "res_h"}
}
sub apply_scale {
    my ($name) = @_;
    $theme{conf}{$name} = $adj{$name}->get_value;
    update_rect();
    $image_area->queue_draw;
}
sub check_scale_value {
    my ($changed, $linked) = @_;
    my $max = get_scale_max($changed) - $adj{$changed}->get_value;
    $adj{$linked}->get_value > $max and $adj{$linked}->set_value($max);
}
sub update_scales_for_resolution() {
    $theme{conf}{$_} ||= get_scale_max($_) * $scale_settings{$_}[0] foreach keys %scale_settings;
    $adj{$_}->upper(get_scale_max($_)) foreach keys %adj;
}
sub update_scale_values_from_conf() {
    foreach (keys %adj) {
        $adj{$_}->signal_handler_block($adj{$_}{on_change});
        $adj{$_}->set_value($theme{conf}{$_});
        $adj{$_}->signal_handler_unblock($adj{$_}{on_change});
    }
}

sub create_image_area() {
    my $image_area = Gtk2::DrawingArea->new;
    $image_area->can_focus(1);
    $image_area->add_events($_) foreach qw(button-press-mask pointer-motion-mask);
    $image_area->signal_connect(motion_notify_event => \&image_motion_notify);
    $image_area->signal_connect(button_press_event => \&image_button_pressed);
    $image_area->signal_connect(expose_event => \&image_expose);
    $image_area->signal_connect(key_press_event => sub {
	my (undef, $event) = @_;
	member($event->keyval, 'q', 'Escape') and close_all();
	1;
    });
    $image_area->grab_focus;
    $image_area->show;
    $image_area;
}

sub image_expose {
    my ($widget) = @_;
    my $window = $widget->window;
    $window->draw_pixbuf($widget->style->white_gc, $image_pixbuf[$current_mode > 0], 0, 0, 0, 0, -1, -1, 'none', 0, 0) if $image_pixbuf[$current_mode > 0];
    my $cross_gc;
    if ($current_mode == 0) { #- silent
	$window->draw_rectangle($widget->style->white_gc, 1, @{$theme{conf}}{'px', 'py', 'pw', 'ph'});
	$cross_gc = $widget->style->black_gc;
    } else { #- verbose or console
	$window->draw_rectangle($widget->style->black_gc, 0, @{$theme{conf}}{'tb_x', 'tb_y', 'tb_w', 'tb_h'});
	$cross_gc = $widget->style->white_gc;
    }
    $window->draw_line($cross_gc, $current_rect->[0]{X}, $current_rect->[0]{Y}, $current_rect->[1]{X}, $current_rect->[1]{Y});
    $window->draw_line($cross_gc, $current_rect->[0]{X}, $current_rect->[1]{Y}, $current_rect->[1]{X}, $current_rect->[0]{Y});
}

sub update_rect() {
    undef $current_point;
    if ($current_mode == 0) { #- silent
	$current_rect = bootsplash::xywh2rectangle(@{$theme{conf}}{'px', 'py', 'pw', 'ph'});
    } else { #- verbose or console
	$current_rect = bootsplash::xywh2rectangle(@{$theme{conf}}{'tb_x', 'tb_y', 'tb_w', 'tb_h'});
    }
}

sub switch_to_mode {
    my ($mode) = @_;
    $current_mode = $mode;
    update_rect();
    $image_area->queue_draw;
}

sub update_theme_from_rect() {
    if ($current_mode == 0) { #- silent
	@{$theme{conf}}{'px', 'py', 'pw', 'ph'} = bootsplash::rectangle2xywh($current_rect);
    } else { #- verbose or console
	@{$theme{conf}}{'tb_x', 'tb_y', 'tb_w', 'tb_h'} = bootsplash::rectangle2xywh($current_rect);
    }
    update_scale_values_from_conf();
    $image_area->queue_draw;
}

sub image_button_pressed {
    my (undef, $event) = @_;
    my $point = { X => $event->x, Y => $event->y };
    $current_point = bootsplash::nearest($point, @$current_rect);
    %$current_point = %$point;
    update_theme_from_rect();
}

sub restrict_to_interval {
    my ($x, $min, $max) = @_;
    max($min, min($max, $x));
}

sub image_motion_notify {
    my (undef, $event) = @_;
    member('button1-mask', @{$event->state}) or return;
    %$current_point = (
        X => restrict_to_interval($event->x, 0, $theme{res_w}),
        Y => restrict_to_interval($event->y, 0, $theme{res_h}),
    ) if $current_point;
    update_theme_from_rect();
}