#!/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 $thm_conf_path = '/etc/bootsplash/themes/';

my $prev_window;
my $pix;

my $boot_conf_path = '/etc/bootsplash/themes/';
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' => new Gtk2::Frame(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 ]
                     }
             },
             'pos' => [ 'name', 'res', 'file', 'boot_conf', #'save', #'kill'
					],
             );
my %boot_conf_frame = ('frame' => new Gtk2::Frame(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
my @action_frame = (\%boot_conf_frame , \%first);
my $VB2 = new Gtk2::VBox(0,5);
my $first_vbox = new Gtk2::VBox(0,5);

&mk_frame($VB2, \%first);
#****************************- 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} = new Gtk2::Frame(N("Configure bootsplash picture"));
	&make_boot_frame;
	$first_vbox->add($boot_conf_frame{frame});
	member($theme{name}, &giv_exist_thm) and &thm_in_this_res and &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($first{widgets}{label}{file}->get_text ne N("choose image file") ? $first{widgets}{label}{file}->get_text : '~/');
	$file_dialog->cancel_button->signal_connect(clicked => sub { $file_dialog->destroy });
	$file_dialog->ok_button->signal_connect(clicked => sub { $first{widgets}{label}{file}->set_text($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 = $thm_conf_path.$theme{name}.'/global.config';
	my $cfg_file = $thm_conf_path.$theme{name}.'/cfg/bootsplash-'.$theme{res}{res}.'.cfg';
	#- verify all dir exists or create them
	-d $thm_conf_path.$theme{name}
	  or mkdir($thm_conf_path.$theme{name});
	-d $thm_conf_path.$theme{name}.'/cfg'
	  or mkdir($thm_conf_path.$theme{name}.'/cfg');
	-d $thm_path.$theme{name}
	  or mkdir($thm_path.$theme{name});
	-d $thm_path.$theme{name}.'/images/'
	  or mkdir($thm_path.$theme{name}.'/images/');
	#- copy image to dest by convert
	system('convert -scale '.$theme{res}{res} . ' ' . $first{widgets}{label}{file}->get.' '.$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 $first{widgets}{label}{file}->set_text($thm_path.$theme{name}."/images/bootsplash-".$theme{res}{res}.".jpg");
	  return 1;
}

sub read_boot_conf {
	chdir($thm_conf_path);
	my $line;
	if (-f $theme{name}.'/cfg/bootsplash-'.$theme{res}{res}.'.cfg') {
          local *CFG;
		open CFG , $theme{name}.'/cfg/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}}) {
		 -f "bootsplash-$_.jpg"
		   and $is_ok = 1
		   and $first{widgets}{combo}{res}->entry->set_text($_)
		   and 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'} = new Gtk2::Tooltips();
		  $adj{$name.'_tip'}->set_tip($ref->{widgets}{$_}{$name}, $ref->{widget}{tooltip}{$name}, '');
		}
	}
}

my %hboxes;

#- 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 ($box , $ref) = @_;
	foreach my $pos (@{$ref->{pos}}) {
       my $key = $1.'hb' if $pos =~ m/^(\w+)(\s+)?(\w+)?$/;
	  #- open a new hbox
	  $hboxes{$key} = new Gtk2::HBox($3 ? 1 : 0, 5);
	  #- look for label
	  $ref->{widget}{label}{$1}
	    and $ref->{widgets}{label}{$1} = new Gtk2::Label($ref->{widget}{label}{$1}) 
	    and $hboxes{$key}->add($ref->{widgets}{label}{$1});
	  #- look for scale
	  $ref->{widget}{scale}{$1}
	    and $ref->{widgets}{scale}{$1} = new Gtk2::HScale($adj{$1} =  new Gtk2::Adjustment(0, 0, $scale_size{$1}, 1, 10, 0))
	    and $hboxes{$key}->add($ref->{widgets}{scale}{$1})
	    and $ref->{widgets}{scale}{$1}->set_digits(0);
	  $adj{$1} and $adj{$1}->set_value($theme{boot_conf}{$1});
	  #- look for combo
       my @popdown;
	  $ref->{widget}{combo}{$1} 
	    and @popdown = @{$ref->{widget}{combo}{$1}}
	    and $ref->{widgets}{combo}{$1} = new Gtk2::Combo
	    and $hboxes{$key}->add($ref->{widgets}{combo}{$1})
	    and $ref->{widgets}{combo}{$1}->set_popdown_strings(@popdown);
	  #- look for checkbox
	  $ref->{widget}{check}{$1}
	    and $ref->{widgets}{check}{$1} = new Gtk2::CheckButton($ref->{widget}{check}{$1})
	    and $hboxes{$key}->add($ref->{widgets}{check}{$1})
	    and $ref->{widgets}{check}{$1}->set_active(1);
	  #- look for button
	  $ref->{widget}{button}{$1}
	    and $ref->{widgets}{button}{$1} = new Gtk2::Button($ref->{widget}{button}{$1})
	    and  $hboxes{$key}->add($ref->{widgets}{button}{$1});
	  #- look for tooltips
	  $ref->{widget}{tooltip}{$1} and &tool_tip($1, \%$ref);
	  $box->add($hboxes{$key});
	}
	$ref->{frame}->add($box);
}

#- 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() {
	my $VB = new Gtk2::VBox(0,5);
	&mk_frame($VB, \%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(Gtk2::Gdk::Color->new(@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 => sub { &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 {
	  my $w = $first{widgets}{label}{file};
	  unless (-f $w->get_text) {
	    $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($first{widgets}{label}{file}->get,$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 => sub { &check_boot_scales($k) });
	}
}

#- 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_pix, $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);
		undef($prev_pix);
}
#- Desc  => create a new window with a preview of splash screen
#- Args  => $file (str) full path to preview file
sub show_prev {
 my ($file, $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 = new Gtk2::Window('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($file);
 $prev_pic->scale_simple($theme{res}{w}, $theme{res}{h},0);
 $prev_pix = $prev_pic->render_pixmap_and_mask($prev_pic);
 $prev_canvas && $prev_canvas->isa('Gtk2::Widget')
	 or $prev_canvas = new Gtk2::DrawingArea() and $prev_window->add($prev_canvas);
 $prev_canvas->set_size_request($theme{res}{w}, $theme{res}{h});
 $prev_canvas->signal_connect(expose_event => sub {
     $prev_canvas->window->draw_pixmap($prev_canvas->style->bg_gc('normal'),$prev_pix,0,0,0,0, $theme{res}{w}, $theme{res}{h});
     $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);
  
}