#!/usr/bin/perl 

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

#- convenience variables for true and false
my $true = 1;


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

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

#- verification of package image magik
unless ($in->do_pkgs->is_installed('ImageMagick')) {
    $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 CloseAppWindow();
}

#- application vars
my $tmp_path = '/tmp/draksplash/';
! -d $tmp_path and mkdir($tmp_path);
my $thm_path = '/usr/share/bootsplash/themes/';
my $boot_conf_path = '/etc/bootsplash/themes/';
my $cfg_path = "/cfg/";

my $img_file;

my $prev_window;

my %font_size = ('h' =>16, 'w' =>8);
my %theme = ('name' => 'new_theme',
             'res' => {
                 'res' => '800x600',
                 'h' => '600',
                 'w' => '800',
             },
             'boot_conf' => { 
                 'tx' => 0,
                 'ty' => 0,
                 'tw' => 0,
                 'th' => 0,
                 'px' => 0,
                 'py' => 0,
                 'pw' => 0,
                 'ph' => 0,
                 'pc' => '0x21459d',
             },
             'boot_img' => ''
             );

my %scale_size = ('tx' => ($theme{res}{w} / $font_size{w}),
                  'ty' => ($theme{res}{h} / $font_size{h}),
                  'tw' => ($theme{res}{w} / $font_size{w}),
                  'th' => ($theme{res}{h} / $font_size{h}),
                  'px' => $theme{res}{w},
                  'py' => $theme{res}{h},
                  'pw' => $theme{res}{w},
                  'ph' => $theme{res}{h},
                  );

my %first = ('frame' => Gtk2::Frame->new(N("first step creation")),
             'widget' => { 
                 'label' => {
                     'res' => N("final resolution"),
                     'file' => N("choose image file"),
                     'name' => N("Theme name")
                     },
                         'button' => {
                             #'boot_conf' => N("Make bootsplash step 2"),
                             #'lilo_conf' => N("Go to lilosplash configuration"),
                             'file' => N("Browse"),
                         },
                 'combo' => { 
                     'res' => ['800x600', '1024x768', '1280x1024'],
                     'name' => [ $theme{name}, giv_exist_thm() ]
                     },
                          extras => {
                                     res => {
                                             noneditable => 1,
                                            },
                                    },
             },
             'pos' => [ 'name', 'res', 'file', 'boot_conf', #'save', #'kill'
					],
             );
my %boot_conf_frame = ('frame' => Gtk2::Frame->new(N("Configure bootsplash picture")),
                       'widget' => {
                           'label' => {
                               'tx' => N("x coordinate of text box\nin number of characters"),
                               'ty' => N("y coordinate of text box\nin number of characters"),
                               'tw' => N("text width"),
                               'th' => N("text box height"),
                               'px' => N("the progress bar x coordinate\nof its upper left corner"),
                               'py' => N("the progress bar y coordinate\nof its upper left corner"),
                               'pw' => N("the width of the progress bar"),
                               'ph' => N("the height of the progress bar"),
                               'pc' => N("the color of the progress bar")
                               },
                           #- must set scale values to true to get them created by mk_frame
                           'scale' => {
                               'tx' => 1,
                               'ty' => 1,
                               'tw' => 1,
                               'th' => 1,
                               'px' => 1,
                               'py' => 1,
                               'pw' => 1,
                               'ph' => 1,
                           },
                           'button' => {
                               #'annul' => N("Go back"),
                               'prev' => N("Preview"),
                               'kill' => N("Quit"),
                               'save' => N("Save theme"),
                               'pc' => N("Choose color"),
                           },
                           'check'  => {
                               'logo' => N("Display logo on Console"),
                               'quiet' => N("Make kernel message quiet by default"),
                           },
                       },
                       'pos' => [ 'tx 1', 
                                  'ty 1',
                                  'tw 1', 
                                  'th 1',
                                  'px 1',
                                  'py 1',
                                  'pw 1',
                                  'ph 1',
                                  'pc',
                                  'logo',
                                  'quiet',
                                  'annul',
                                  'prev',
                                  'save',
                                  'kill',
                                  ],
                       );
#- var action is used to hide/show the correct frame
$first{frame}->add(mk_frame(\%first));
my $first_vbox = Gtk2::VBox->new(0, 5);


#****************************- Signal event actions
#- change resolution 
$first{widgets}{combo}{res}->entry->signal_connect(changed => sub {
	$theme{res}{res} = $first{widgets}{combo}{res}->entry->get_text;
	($theme{res}{w}, $theme{res}{h}) = $theme{res}{res} =~ /([^x]+)x([^x]+)/;
	&set_scale_size;
	$boot_conf_frame{frame}->destroy;
	$boot_conf_frame{frame} = Gtk2::Frame->new(N("Configure bootsplash picture"));
	&make_boot_frame;
	$first_vbox->add($boot_conf_frame{frame});
	member($theme{name}, giv_exist_thm()) && thm_in_this_res() && get_this_thm_res_conf() || $in->ask_warn(N("Notice"), N("This theme does not yet have a bootsplash in %s !", $theme{res}{res}));
      });
#- go to bootsplash configuration step 2
#$first{widgets}{button}{boot_conf}->signal_connect(clicked => sub{show_act(\%boot_conf_frame) } );
#- image file selection for new theme
$first{widgets}{button}{file}->signal_connect(clicked => sub {
	my $file_dialog = gtkset_modal(Gtk2::FileSelection->new(N("choose image")), 1);
	$file_dialog->set_transient_for($window->{rwindow});

	$file_dialog->set_filename($img_file || '~/');
	$file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
	$file_dialog->ok_button->signal_connect(clicked => sub { $img_file = $file_dialog->get_filename; $file_dialog->destroy });
	$file_dialog->show;
});
#- changing theme name
$first{widgets}{combo}{name}->entry->signal_connect(changed => sub { get_this_thm_res_conf(); $theme{name} = $first{widgets}{combo}{name}->entry->get_text });
#**************************************************


$first_vbox->add($first{frame});
$first_vbox->add($boot_conf_frame{frame});
&make_boot_frame;

# set window attributes and show it

unless ($::isEmbedded) {
    $window->{rwindow}->set_border_width(5);
    $window->{window}->add($first_vbox);
    $window->{rwindow}->set_position('center');
    $window->{rwindow}->show_all;
#&show_act(\%first);
}

# Gtk event loop
$window->main;

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

### Callback function to close the window
sub CloseAppWindow() {
   ugtk2->exit(0);
}

#- ====## used funtions ##=====

#- Desc  => write config file for boot theme and copy image in the right location
sub write_boot_thm {
	my $_w = $in->wait_message('', N("saving Bootsplash theme..."));
  	&set_thm_values;
  	my $logo = $boot_conf_frame{widgets}{check}{logo}->get_active ? 'yes' : 'no';
	my $quiet = $boot_conf_frame{widgets}{check}{quiet}->get_active ? 'yes' : 'no';
	my $globalconf_file = $boot_conf_path.$theme{name}.'/global.config';
	my $cfg_file = $boot_conf_path . $theme{name} . "$cfg_path/bootsplash-" . $theme{res}{res} . '.cfg';
	#- verify all dir exists or create them
     foreach my $dir ($boot_conf_path . $theme{name} . $cfg_path, $thm_path.$theme{name} . '/images/') {
         mkdir_p($dir) if !-d $dir;
     }
	#- copy image to dest by convert
	system('convert -scale '.$theme{res}{res} . ' ' . $img_file . ' ' . $thm_path.$theme{name} . '/images/bootsplash-' . $theme{res}{res} . '.jpg');
	system('/usr/share/bootsplash/scripts/rewritejpeg '.$thm_path.$theme{name}.'/images/bootsplash-'.$theme{res}{res}.'.jpg');
	#- write conf files
	my $cfg_cont = '# This is the configuration file for the '.$theme{res}{res}.' bootsplash picture
# this file is necessary to specify the coordinates of the text box on the
# splash screen.

# tx is the x coordinate of the text window in characters. default is 24
# multiply width font width for coordinate in pixels.
tx='.$theme{boot_conf}{tx}.'

# ty is the y coordinate of the text window in characters. default is 14
ty='.$theme{boot_conf}{ty}.'

# tw is the width of the text window in characters. default is 130
# note: this should at least be 80 as on the standard linux text console
tw='.$theme{boot_conf}{tw}.'

# th is the height of the text window in characters. default is 44
# NOTE: this should at least be 25 as on the standard linux text console
th='.$theme{boot_conf}{th}.'

# px is the progress bar x coordinate of its upper left corner
px='.$theme{boot_conf}{px}.'

# py is the progress bar y coordinate of its upper left corner
py='.$theme{boot_conf}{py}.'

# pw is the with of the progress bar
pw='.$theme{boot_conf}{pw}.'

# ph is the height of the progress bar
ph='.$theme{boot_conf}{ph}.'

# pc is the color of the progress bar
pc='.$theme{boot_conf}{pc}.'';
	my $globalconf_cont = '# Display logo on console.
LOGO_CONSOLE='.$logo.'

# Make kernel message quiet by default.
QUIET='.$quiet;
	output($globalconf_file, $globalconf_cont);
	output($cfg_file, $cfg_cont);
}


#- Desc  => read the current bootsplash theme configuration if exist
sub get_this_thm_res_conf() {
  	member($first{widgets}{combo}{name}->entry->get_text, giv_exist_thm())
	  and $theme{name} = $first{widgets}{combo}{name}->entry->get_text
	  and thm_in_this_res(1) 
	  and read_boot_conf();
	  -f $thm_path.$theme{name}."/images/bootsplash-".$theme{res}{res}.".jpg"
	    and $img_file = $thm_path . $theme{name} . "/images/bootsplash-" . $theme{res}{res} . ".jpg";
	  return 1;
}

sub read_boot_conf {
	chdir($boot_conf_path);
	my $line;
	if (-f $theme{name} . "/$cfg_path/bootsplash-" . $theme{res}{res} . '.cfg') {
          local *CFG;
		open CFG, $theme{name} . "/$cfg_path/bootsplash-" . $theme{res}{res} . '.cfg';
	  	while ($line = <CFG>) {
			$line =~ m/^([a-z][a-z])=([^\n]+)/
			  and $theme{boot_conf}{$1} = $2;
		}
		close CFG;
		&set_scale_values;
	} else {
		return 0;
	}
}

my %adj;
sub set_scale_values() {
    foreach (keys %{$theme{boot_conf}}) {
        $adj{$_} and $adj{$_}->set_value($theme{boot_conf}{$_});
    }
}

#- Desc  => check if this theme is available in the current resolution else
#-	    change the current resolution or display a ask_warn box
#- Args  => �
#- return=> (bool)
sub thm_in_this_res {
  my ($check_res) = @_;
  (-f $thm_path.$theme{name}."/images/bootsplash-".$theme{res}{res}.".jpg") ? return 1 : $check_res == 1 ? return which_res_exist() : return 0;
}

sub which_res_exist() {
	chdir($thm_path.$theme{name}."/images/");
	my $is_ok = 0;
	foreach (@{$first{widget}{combo}{res}}) {
         next if !-f "bootsplash-$_.jpg";
         $is_ok = 1;
         $first{widgets}{combo}{res}->entry->set_text($_);
         last;
	}
	$is_ok == 1 or $in->ask_warn(N("Notice"), N("This theme does not yet have a bootsplash in %s !", $theme{res}{res})) and return 0;
	return 1;
}	

#- Desc  => retrieve all installed theme
#- Args  => �
#- Return=> @arr of available theme
sub giv_exist_thm() {
  chdir($thm_path);
  my @thms_dirs;
  foreach (glob("*")) {
    -d  $_ && m/^[^.]/ 
      and push @thms_dirs, $_;
  }
  return @thms_dirs;
}

#- Desc  => show only the right frame
#- Args  => action(str)
#- Return=> (bool)
sub show_act {
#    my ($action) = @_;
#    foreach (@action_frame){
#	if($_ == $action){
#	    $_->{frame}->show_all ;
#	}else{
#	    $_->{frame}->hide;
#	}
#    }
}

#- Desc  => just add tooltips
#- Args  => name of widget(str) and frame to work on it (\%hash)
sub tool_tip {
	my ($name, $ref) = @_;
	foreach (keys %{$ref->{widget}}) {
		$_ eq 'tooltip' and next;
	  	if ($ref->{widget}{$_}{$name}) {
		  ! $adj{$name.'_tip'} and $adj{$name.'_tip'} = Gtk2::Tooltips->new;
		  $adj{$name.'_tip'}->set_tip($ref->{widgets}{$_}{$name}, $ref->{widget}{tooltip}{$name}, '');
		}
	}
}


#- Desc  => just prepare widgets for a fram hash 
#- Args  => $box(a Vbox widget to contain all widgets), \%frame (hash with complete definition of the frame)
#- Return=> all hash{widgets} are created and packed in $box
sub mk_frame {
    my ($ref) = @_;
    my @buttons;
    my $u = create_packtable({ col_spacings => 10, row_spacings => 5 },
                             map {
                                 my @widgets;

                                 #- look for label
                                 if ($ref->{widget}{label}{$1}) {
                                     my $w = $ref->{widgets}{label}{$1} = Gtk2::Label->new($ref->{widget}{label}{$1});
                                     push @widgets, $w;
                                 }

                                 #- look for scale
                                 if ($ref->{widget}{scale}{$1}) {
                                     my $w = $ref->{widgets}{scale}{$1} = Gtk2::HScale->new($adj{$1} =  Gtk2::Adjustment->new(0, 0, $scale_size{$1}, 1, 10, 0));
                                     $ref->{widgets}{scale}{$1}->set_digits(0);
                                     push @widgets, $w;
                                 }
                                 $adj{$1} and $adj{$1}->set_value($theme{boot_conf}{$1});

                                 #- look for combo
                                 my @popdown;
                                 if ($ref->{widget}{combo}{$1}) {
                                     @popdown = @{$ref->{widget}{combo}{$1}};
                                     my $w = $ref->{widgets}{combo}{$1} = $ref->{widget}{extras}{$1}{noneditable} ? Gtk2::OptionMenu->new : Gtk2::Combo->new;
                                     $ref->{widgets}{combo}{$1}->set_popdown_strings(@popdown);
                                     push @widgets, $w;
                                 }

                                 #- look for checkbox
                                 if ($ref->{widget}{check}{$1}) {
                                     my $w =  $ref->{widgets}{check}{$1} = Gtk2::CheckButton->new($ref->{widget}{check}{$1});
                                     $ref->{widgets}{check}{$1}->set_active(1);
                                     push @widgets, $w;
                                 }

                                 #- look for button
                                 if ($ref->{widget}{button}{$1}) {
                                     my $w =  $ref->{widgets}{button}{$1} = Gtk2::Button->new($ref->{widget}{button}{$1});
                                     @widgets ?
                                       push @widgets, $w
                                         : push @buttons, $w;
                                 }

                                 #- look for tooltips
                                 $ref->{widget}{tooltip}{$1} and tool_tip($1, \%$ref);
                                 if_(@widgets, \@widgets);
                             } @{$ref->{pos}}
                            );
    
    gtkpack__(Gtk2::VBox->new,
              gtkset_border_width($u, 3),
              @buttons);
}

#- Desc  => take a decimal value between 0 to 255 and return the corresponding hexadecimal value
sub dec2hex {
	my ($dec) = @_;
	my @dec_hex = (0..9, 'A', 'B', 'C', 'D', 'E', 'F');
	my $int; 
	my $float;
	$dec = $dec/16;
	$int = int($dec);
	$float = $dec_hex[int(($dec-$int)*16)];
	$int = $dec_hex[$int];
	
	return "$int$float";
}

#- Desc  => prepare and set all signal_connect for boot_frame widget 
sub make_boot_frame() {
    $boot_conf_frame{frame}->add(mk_frame(\%boot_conf_frame));

	#- open a color choose box
	$boot_conf_frame{widgets}{button}{pc}->signal_connect(clicked => sub {
		my $color = gtkshow(Gtk2::ColorSelectionDialog->new(N("ProgressBar color selection")));
		my @rgb = map { hex($_)/255 } ($1, $2, $3) if $theme{boot_conf}{pc} =~ m/0x(.{2})(.{2})(.{2})/;
		$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;
			@rgb = map { dec2hex($_*255) } ($colour->red, $colour->green, $colour->blue);
			$theme{boot_conf}{pc} =  "0x$rgb[0]$rgb[1]$rgb[2]";
			$color->destroy;
		});
	}); 
	#- quit button
	$boot_conf_frame{widgets}{button}{kill}->signal_connect(clicked => \&CloseAppWindow);
	$boot_conf_frame{widgets}{button}{save}->signal_connect(clicked => \&write_boot_thm);
	#- return to first screen
	#$boot_conf_frame{widgets}{button}{annul}->signal_connect(clicked => sub { show_act( \%first ) } );
	#- made a preview
	$boot_conf_frame{widgets}{button}{prev}->signal_connect(clicked => sub {
	  unless (-f $img_file) {
	    $in->ask_warn(N("Notice"), N("You must choose an image file first!"));
	    return 0;
	  }
	  #- calculation of the 2 angle of text box and progress bar
	  set_thm_values();
	  my $_w = $in->wait_message('', N("Generating preview ..."));
       my $txt_tl_x 	= $theme{boot_conf}{tx}*$font_size{w}; 
       my $txt_tl_y 	= $theme{boot_conf}{ty}*$font_size{h};
       my $txt_width 	= $theme{boot_conf}{tw}*$font_size{w};
       my $txt_height	= $theme{boot_conf}{th}*$font_size{h};
       my $prog_tl_x 	= $theme{boot_conf}{px};
       my $prog_tl_y 	= $theme{boot_conf}{py};
       my $prog_width	= $theme{boot_conf}{pw};
       my $prog_height  = $theme{boot_conf}{ph};
	  show_prev($txt_tl_x, $txt_tl_y, $txt_width, $txt_height, $prog_tl_x, $prog_tl_y, $prog_width, $prog_height);
	});
	$boot_conf_frame{frame}->show_all;
#	- check scales values are possibly correct
	#&set_scale_values;
	
	foreach my $k (keys %{$theme{boot_conf}}) {
		$k =~ m/[tp][hwyx]/
		  and $adj{$k}->signal_connect(value_changed => \&check_boot_scales);
	}
}

#- Desc  => set theme values from user entry (scales widgets)
sub set_thm_values() {
  foreach (keys %{$theme{boot_conf}}) {
    	m/[tp][hwyx]/
	  and $theme{boot_conf}{$_} = int($adj{$_}->get_value);
  }
}


my ($prev_pic, $prev_canvas);

#- Desc  => destroy properly all widget of preview window
sub kill_preview() {
		$prev_window->destroy; undef($prev_window);
		$prev_canvas->destroy; undef($prev_canvas);
		undef($prev_pic);
}
#- Desc  => create a new window with a preview of splash screen
#- Args  => $img_file (str) full path to preview file
sub show_prev {
 my ($txt_tl_x, $txt_tl_y, $txt_width, $txt_height, $prog_tl_x, $prog_tl_y, $prog_width, $prog_height) = @_;
 $prev_window
   or $prev_window = Gtk2::Window->new('toplevel'); 
#-PO  First %s is theme name, second %s (in parenthesis) is resolution
 $prev_window->set_title(N("%s BootSplash (%s) preview", $theme{name}, $theme{res}{res}));
 $prev_pic = gtkcreate_pixbuf($img_file);
 $prev_pic->scale_simple($theme{res}{w}, $theme{res}{h}, 'hyper');
 $prev_canvas && $prev_canvas->isa('Gtk2::Widget')
	 or $prev_canvas = Gtk2::DrawingArea->new and $prev_window->add($prev_canvas);
 $prev_canvas->set_size_request($theme{res}{w}, $theme{res}{h});
     $prev_canvas->signal_connect(expose_event => sub {
     my ($w, $event) = @_;
     my ($x, $y, $width, $height) = $event->area->values;
     $prev_pic->render_to_drawable($w->window, $w->style->fg_gc('normal'), $x, $y, $x, $y, $width, $height, 'normal', 0, 0);
     $prev_canvas->window->draw_rectangle($prev_canvas->style->black_gc, $true, $txt_tl_x, $txt_tl_y, $txt_width, $txt_height);
     $prev_canvas->window->draw_rectangle($prev_canvas->style->black_gc, $true, $prog_tl_x, $prog_tl_y, $prog_width, $prog_height);
 });
 $prev_window->signal_connect(delete_event => \&kill_preview);
 $prev_window->show_all;
 
}

#- Desc  => define the max size of boot's scales
sub set_scale_size() {
	 %scale_size = ('tx' => ($theme{res}{w} / $font_size{w}),
 			'ty' => ($theme{res}{h} / $font_size{h}),
			'tw' => ($theme{res}{w} / $font_size{w}),
			'th' => ($theme{res}{h} / $font_size{h}),
			'px' => $theme{res}{w},
			'py' => $theme{res}{h},
			'pw' => $theme{res}{w},
			'ph' => $theme{res}{h},
		      );
}

#- Desc  => verify that boot's  scales widgets are correctly set
#- Args  => $obj (str) is the scale to check value

sub check_boot_scales {
  my ($obj) = @_;
  my $tw = $adj{tw}->get_value;
  my $tx = $adj{tx}->get_value;
  my $th = $adj{th}->get_value;
  my $ty = $adj{ty}->get_value;
  my $pw = $adj{pw}->get_value;
  my $ph = $adj{ph}->get_value;
  my $px = $adj{px}->get_value;
  my $py = $adj{py}->get_value;
  my $max_x = $scale_size{tw};
  my $max_y = $scale_size{th};
  my $max_xres = $theme{res}{w};
  my $max_yres = $theme{res}{h};
  
  $obj eq 'tw' and $max_x < $tw + $tx and $adj{tx}->set_value($max_x - $tw);
  $obj eq 'tx' and $max_x < $tw + $tx and $adj{tw}->set_value($max_x - $tx);
  $obj eq 'th' and $max_y < $th + $ty and $adj{ty}->set_value($max_y - $th);
  $obj eq 'ty' and $max_y < $th + $ty and $adj{th}->set_value($max_y - $ty);
  $obj eq 'pw' and $max_xres < $pw + $px and $adj{px}->set_value($max_xres - $pw);
  $obj eq 'px' and $max_xres < $pw + $px and $adj{pw}->set_value($max_xres - $px);
  $obj eq 'ph' and $max_yres < $ph + $py and $adj{py}->set_value($max_yres - $ph);
  $obj eq 'py' and $max_yres < $ph + $py and $adj{ph}->set_value($max_yres - $py);
  
}