#!/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');

#- verification of package image magik
unless ($in->do_pkgs->ensure_is_installed('ImageMagick', '/usr/bin/convert')) {
    $in->ask_okcancel(N("Error"), N("package 'ImageMagick' is required to be able to complete configuration.\nClick \"Ok\" to install 'ImageMagick' or \"Cancel\" to quit")) 
        && $in->do_pkgs->install('ImageMagick')
        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 = (
		      tx => [ 1/10, N("x coordinate of text box\nin number of characters") ],
		      ty => [ 1/10, N("y coordinate of text box\nin number of characters") ],
		      tw => [ 8/10, N("text width") ],
		      th => [ 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") ],
		     );

my %adj;
create_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'),
				 gtksignal_connect(Gtk2::Button->new(N("Choose progress bar color")), clicked => \&choose_color),
				 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('tx', 'tw', 'ty', 'th'),
				 gtksignal_connect(Gtk2::Button->new(N("Choose progress bar color")), clicked => \&choose_color),
				 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);
    }
    if (-f $theme{conf}{jpeg}) {
	load_image($theme{conf}{jpeg}, 1);
    }
    $theme{conf}{pc} ||= '0x21459d';
    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, $o_mode) = @_;
    my $mode = $o_mode;
    unless ($mode) {
	$mode = 0;
	@image_pixbuf = ();
    }
    $image_pixbuf[$mode] = Gtk2::Gdk::Pixbuf->new_from_file($img);
    $image_pixbuf[$mode] = $image_pixbuf[$mode]->scale_simple($theme{res_w}, $theme{res_h}, 'hyper');
    $image_pixbuf[1-$mode] or $image_pixbuf[1-$mode] = $image_pixbuf[$mode];
    $image_area->queue_draw;
}

sub choose_image {
    my ($name) = @_;
    my $file_dialog = Gtk2::FileChooserDialog->new(N("choose image"), $window->{real_window}, 'open', N("Cancel") => 'cancel', N("Ok") => 'ok');
    $file_dialog->set_filename($theme{$name} || '~/');
    $file_dialog->show;
    while (my $answer = $file_dialog->run) {
	if (member($answer, qw(cancel delete-event))) {
	    $file_dialog->destroy;
	    return;
	} elsif ($answer eq 'ok') {
	    load_image(my $img = $file_dialog->get_filename);
	    $theme{conf}{$name} = $img;
	    $file_dialog->destroy;
	    return;
	}
    }
}

sub choose_color() {
    my $color = gtkshow(Gtk2::ColorSelectionDialog->new(N("ProgressBar color selection")));
    my @rgb = $theme{boot_conf}{pc} =~ m/0x(.{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{boot_conf}{pc} = "0x" . join('', map { print "$_\n"; sprintf("%x", $_*255) } $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 = (tx => 'tw', ty => 'th', px => 'pw', py => 'ph');
    while (my ($n1, $n2) = each(%scale_links)) {
	$adj{$n1}->signal_connect(value_changed => sub { check_scale_value($n1, $n2); apply_scale($n1) });
	$adj{$n2}->signal_connect(value_changed => sub { check_scale_value($n2, $n1); apply_scale($n2) });
    }
}
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) = @_;
    $theme{$name =~ /[xw]$/ ? "res_w" : "res_h"};
}
sub apply_scale {
    my ($name) = @_;
    $theme{conf}{$name} = $adj{$name}->get_value;
    $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() {
    $adj{$_}{value} = $theme{conf}{$_} foreach keys %adj;
}

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}}{'tx', 'ty', 'tw', 'th'});
	$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}}{'tx', 'ty', 'tw', 'th'});
    }
}

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}}{'tx', 'ty', 'tw', 'th'} = 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 image_motion_notify {
    my (undef, $event) = @_;
    member('button1-mask', @{$event->state}) or return;
    my $point = { X => $event->x, Y => $event->y };
    $current_point and %$current_point = %$point;
    update_theme_from_rect();
}