#!/usr/bin/perl

use POSIX;
use Gtk;
use lib qw(/usr/lib/libDrakX);
use interactive;
use standalone;
use timezone;
init Gtk;
Gtk->set_locale;
#use strict;
use MDK::Common;

#-------------------------------------------------------------
# i18n routines
# IMPORTANT: next two routines have to be redefined here to
#         get correct namespace (drakconf instead of libDrakX)
#         (This version is now UTF8 compliant - Sg 2001-08-18)
#-------------------------------------------------------------

sub _ {
    my $s = shift @_; my $t = translate($s);
    sprintf $t, @_;
}

sub translate {
    my ($s) = @_;
    $s ? c::dgettext('drakconf', $s) : '';
}

$::isEmbedded = ($::XID, $::CCPID) = "@ARGV" =~ /--embedded (\w+) (\w+)/;
my $in = vnew interactive('su');
my $pixmap;
my $radius;
my $dRadians_hour;
my $dRadians_min;
my $dRadians_sec;
my $Radian;
my $timer;
my ($midx, $midy);
my $first=1;
my $is24;
my $h_old;
my ($old_year, $old_month, $old_day);
my $its_reset=0;
my $window = $::isEmbedded ? new Gtk::Plug ($::XID) : new Gtk::Window -toplevel;
my $vbox = new Gtk::VBox(0,0);
$window->set_title(_("DrakClock"));
$window->add($vbox);
$window->signal_connect ( delete_event => \&quit_global );
my $hbox = new Gtk::HBox(0,0);
$vbox->pack_start($hbox, 1, 1, 0);
my $vbox1 = new Gtk::VBox(0,0);
$hbox->pack_start($vbox1, 1, 1, 0);
my $calendar = new Gtk::Calendar;
$vbox1->pack_start($calendar, 1, 1, 0);
$calendar->signal_connect ( $_ => \&cal_changed )
  foreach ('month-changed', 'day-selected', 'day-selected-double-click', 'prev-month', 'next-month', 'prev-year', 'next-year');

my $button_time = new Gtk::Button _("Time Zone");
$vbox1->pack_start($button_time, 0, 1, 10);
$button_time->signal_connect ( clicked => sub {
				   local $::isEmbedded = 0;
				   $in->{timezone}={};
				   add2hash($in->{timezone}, { timezone::read('') });
				   my $timezone = $in->{timezone}{timezone};
				   $in->{timezone}{timezone} = $in->ask_from_treelist(_("Timezone - DrakClock"), _("Which is your timezone?"), '/', [ timezone::getTimeZones('') ], $timezone);
				   if( defined($in->{timezone}{timezone}) ){
					   $in->{timezone}{UTC} = $in->ask_yesorno(_("GMT - DrakClock"), _("Is your hardware clock set to GMT?"), $in->{timezone}{UTC});
					   timezone::write('', $in->{timezone});
				   } else {
					   $in->{timezone}{timezone} = $timezone;
     }
			       });
my $vbox2 = new Gtk::VBox(0,0);
$hbox->pack_start($vbox2, 1, 1, 0);
my $drawing_area = new Gtk::DrawingArea;
$drawing_area->size(300,300);
$vbox2->pack_start($drawing_area, 1, 1, 0);
$drawing_area->set_events(['button_press_mask', 'button_release_mask', "pointer_motion_mask" ]);
$drawing_area->signal_connect ( expose_event => \&expose_event );
$drawing_area->signal_connect ( configure_event => \&configure_event );
$drawing_area->signal_connect ( button_press_event => sub { $pressed=1 });
$drawing_area->signal_connect ( button_release_event => sub { $first=1; $pressed=0 });
$drawing_area->signal_connect ( motion_notify_event => \&motion_event );

my $hbox11 = new Gtk::HBox(1,0);
$vbox2->pack_start($hbox11, 0, 0, 10);
my $hbox2 = new Gtk::HBox(1,0);
$hbox11->pack_start($hbox2, 0, 0, 0);
my $adj_h = new Gtk::Adjustment 0.0, 0.0, 23.0, 1.0, 5.0, 0.0;
my $spinner_h = new Gtk::SpinButton $adj_h, 0, 0;
$hbox2->pack_start($spinner_h, 0, 0, 0);
$spinner_h->set_wrap(1);
$spinner_h->signal_connect ( activate => \&spinned);
$spinner_h->signal_connect ( button_release_event => \&spinned);
$spinner_h->signal_connect ( changed => \&changed );
my $adj_m = new Gtk::Adjustment 0.0, 0.0, 59.0, 1.0, 5.0, 0.0;
my $spinner_m = new Gtk::SpinButton $adj_m, 0, 0;
$hbox2->pack_start($spinner_m, 0, 0, 0);
$spinner_m->set_wrap(1);
$spinner_m->signal_connect ( activate => \&spinned );
$spinner_m->signal_connect ( button_release_event => \&spinned );
my $adj_s = new Gtk::Adjustment 0.0, 0.0, 59.0, 1.0, 5.0, 0.0;
my $spinner_s = new Gtk::SpinButton $adj_s, 0, 0;
$hbox2->pack_start($spinner_s, 0, 0, 0);
$spinner_s->set_wrap(1);
$spinner_s->signal_connect ( activate => \&spinned );
$spinner_s->signal_connect ( button_release_event => \&spinned );

my $bbox = new Gtk::HButtonBox;
$bbox->set_layout(-end);
$vbox->pack_start($bbox, 0, 0, 5);
my $button_ok = new Gtk::Button _("OK");
$button_ok->signal_connect ( clicked => sub {
				 my ($year, $month, $day) = $calendar->get_date;
				 $month++;
				 my ($hour, $min, $sec) = ($adj_h->get_value, $adj_m->get_value, $adj_s->get_value);
				 $a = "date " .
						  ($month<10 ? "0" : "") . $month .
						  ($day<10 ? "0" : "") . $day .
						  ($hour<10 ? "0" : "") . $hour .
						  ($min<10 ? "0" : "") . $min .
						  $year . "." .
						  ($sec<10 ? "0" : "") . $sec;
				 system($a);
				 -e '/sbin/hwclock' and system('/sbin/hwclock --systohc');
				 quit_global();
			     });
$bbox->add($button_ok );
my $button_cancel = new Gtk::Button _("Cancel");
my $button_reset = new Gtk::Button _("Reset");
$button_cancel->signal_connect ( clicked => sub {
				     quit_global();
				     Gtk->timeout_remove($timer);
				     $timer=Gtk->timeout_add(120, sub { time_to_rad(localtime(time)); Repaint($drawing_area) });
				     time_to_rad(localtime(time)); Repaint($drawing_area);
				     $calendar->select_month($old_month, $old_year);
				     $calendar->select_day($old_day);
				     $button_reset->set_sensitive(0);
				 });
$bbox->add($button_cancel );
$button_reset->signal_connect ( clicked => sub {
				    $its_reset=1;
				    $timer=Gtk->timeout_add(120, sub { time_to_rad(localtime(time)); Repaint($drawing_area) });
				    time_to_rad(localtime(time)); Repaint($drawing_area);
				    $calendar->select_month($old_month, $old_year);
				    $calendar->select_day($old_day);
				    $button_reset->set_sensitive(0);
				    $its_reset=0;
				});
$bbox->add($button_reset);

$window->show_all;

Gtk->main_iteration while Gtk->events_pending;
$calendar->realize;
(undef,undef,$h_old,$old_day,$old_month,$old_year) = localtime(time);
$is24 = $h_old>12;
$old_year += 1900;
$calendar->select_month($old_month, $old_year);
$calendar->select_day($old_day);
$::isEmbedded and kill USR2, $::CCPID;
$button_reset->set_sensitive(0);
$timer=Gtk->timeout_add(120, sub { time_to_rad(localtime(time)); Repaint($drawing_area) });
Gtk->main;

sub cal_changed {
    !$its_reset and $timer and Gtk->timeout_remove($timer);
    $button_reset->set_sensitive(1);
}

sub changed {
    if ($h_old > $adj_h->get_value && $adj_h->get_value < ($is24 ? 18 : 6) && $h_old > ($is24 ? 18 : 6) && $h_old < ($is24 ? 24 : 12)) {
	$h_old= $adj_h->get_value;
	$is24 = !$is24;
    }
    elsif ($h_old < $adj_h->get_value && $adj_h->get_value > ($is24 ? 18 : 6) && $h_old < ($is24 ? 18 : 6) && ($adj_h->get_value-$h_old !=12 )) {
	$h_old= $adj_h->get_value;
	$is24 = !$is24;
    }
    $h_old= $adj_h->get_value;
}

sub spinned {
    Gtk->timeout_remove($timer);
    $button_reset->set_sensitive(1);

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    time_to_rad($adj_s->get_value,$adj_m->get_value,$adj_h->get_value,$mday,$mon,$year,$wday,$yday,$isdst);
    Repaint($drawing_area);
}

sub motion_event {
    my ($widget, $event) = @_;
    $pressed or return;
    if ($first) {
	Gtk->timeout_remove($timer);
	($Radian, $type) = determine_radian($event->{'x'}, $event->{'y'});
	$button_reset->set_sensitive(1);
    }

    $$Radian=-atan2(($event->{'x'}-$midx),($event->{'y'}-$midy)) + $PI;

    Repaint($widget);
    rad_to_time();
    $first=0;
}

sub determine_radian {
    my ($x, $y) = @_;

    my $res;
    my $r;
    my $i=0;
    foreach (\$dRadians_hour, \$dRadians_min, \$dRadians_sec) {
	my $d=sqrt ( ($x - ($midx + 7/10 * $radius * sin ($$_)))**2 + ($y - ($midy - 7/10 * $radius * cos ($$_)))**2 );
	$res or $res=$d, $r=$_;
	$d<$res and $res=$d, $r=$_, $i++;
    }
    ($r, $i);
}

sub quit_global {
    $::isEmbedded ? kill(USR1, $::CCPID) : Gtk->exit(0);
}

sub expose_event {
my ($widget) = @_;
$widget->window->draw_pixmap (
			     $widget->style->fg_gc('normal'),
			     $pixmap,
			     0, 0, 0, 0,
			     $widget->allocation->[2], $widget->allocation->[3]);
}

sub configure_event {
    my ($widget) = @_;
    $pixmap = new Gtk::Gdk::Pixmap ($widget->window,
				    $widget->allocation->[2],
				    $widget->allocation->[3],
				    -1);
    Repaint($widget);
}

sub rad_to_time {
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $adj_h->set_value(POSIX::floor($dRadians_hour * 6 / $PI) + ($is24 ? 12 : 0));
    $adj_m->set_value(POSIX::floor($dRadians_min*30/$PI));
    $adj_s->set_value(POSIX::floor($dRadians_sec*30/$PI));
}

sub time_to_rad {
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @_;
    $dRadians_hour = $hour % 12 * $PI / 6;
    $dRadians_min = $min * $PI / 30;
    $dRadians_sec = $sec * $PI / 30;
    $adj_h->set_value($hour);
    $adj_m->set_value($min);
    $adj_s->set_value($sec);
}

sub Repaint {
    my ($drawing_area) = @_;

    my $dRadians_hour_real = POSIX::floor($dRadians_hour / $PI*6 ) * $PI/6.0 + $dRadians_min / 12;
    my $dRadians_min_real = POSIX::floor($dRadians_min / $PI * 30 ) * $PI / 30;
    my $dRadians_sec_real = $dRadians_sec;
    $pixmap->draw_rectangle($drawing_area->style->white_gc, 1, 0, 0,
			    $drawing_area->allocation->[2],
			    $drawing_area->allocation->[3]);
    $midx = $drawing_area->allocation->[2] / 2;
    $midy = $drawing_area->allocation->[3] / 2;
    $radius = $midx < $midy ? $midx -10 : $midy - 10;

    my $nHour;
    my $gray_gc = $drawing_area->style->bg_gc('normal');
    my $black_gc = $drawing_area->style->black_gc;
    foreach my $i ([\&DrawTickAt, 12], [\&DrawPointAt, 60]) { $i->[0]($pixmap, $black_gc, $gray_gc, $_, $midx, $midy) foreach (1..$i->[1]) }
    my $now = time;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    my $dRadians;
    foreach ([$gray_gc, 5], [$black_gc, 0]) {
	DrawHour ($pixmap, $_->[0], $midx, $midy, $dRadians_hour_real, $_->[1]);
	DrawMin ($pixmap, $_->[0], $midx, $midy, $dRadians_min_real, $_->[1]);
	DrawSec ($pixmap, $_->[0], $midx, $midy, $dRadians_sec_real, $_->[1]);
    }
    $drawing_area->draw(undef);
    1;
}

sub DrawSec {
    my ($pixmap, $gc, $midx, $midy, $dRadians, $dec) = @_;
    $pixmap->draw_line ($gc,
			$midx+$dec, $midy+$dec,
			$midx+$dec + (8/10 * $radius * sin ($dRadians)),
			$midy+$dec - (8/10 * $radius * cos ($dRadians)))
}

sub DrawMin {
    my ($pixmap, $gc, $midx, $midy, $dRadians, $dec) = @_;
    $pixmap->draw_polygon ($gc, 1,
			   $midx+$dec - 3/100 * $radius * sin ($dRadians),
			   $midy+$dec + 3/100 * $radius * cos ($dRadians),
			   $midx+$dec - 3/100 * $radius * sin ($dRadians+$PI/2),
			   $midy+$dec + 3/100 * $radius * cos ($dRadians+$PI/2),
			   $midx+$dec + 8/10 * $radius * sin ($dRadians),
			   $midy+$dec - 8/10 * $radius * cos ($dRadians),
			   $midx+$dec + 3/100 * $radius * sin ($dRadians+$PI/2),
			   $midy+$dec - 3/100 * $radius * cos ($dRadians+$PI/2));
}

sub DrawHour {
    my ($pixmap, $gc, $midx, $midy, $dRadians, $dec) = @_;
    $pixmap->draw_polygon ($gc, 1,
			   $midx+$dec - 5/100 * $radius * sin ($dRadians),
			   $midy+$dec + 5/100 * $radius * cos ($dRadians),
			   $midx+$dec - 5/100 * $radius * sin ($dRadians+$PI/2),
			   $midy+$dec + 5/100 * $radius * cos ($dRadians+$PI/2),
			   $midx+$dec + 7/10 * $radius * sin ($dRadians),
			   $midy+$dec - 7/10 * $radius * cos ($dRadians),
			   $midx+$dec + 5/100 * $radius * sin ($dRadians+$PI/2),
			   $midy+$dec - 5/100 * $radius * cos ($dRadians+$PI/2));
}

sub DrawTickAt {
    my ($pixmap, $black_gc, $gray_gc, $nHour, $cx, $cy) = @_;
    my $dRadians = $nHour * $PI / 6.0;

    $pixmap->draw_line ($_->[0],
			$cx+$_->[1] + 9/10 * $radius * sin ($dRadians),
			$cy+$_->[1] - 9/10 * $radius * cos ($dRadians),
			$cx+$_->[1] + 1 * $radius * sin ($dRadians),
			$cy+$_->[1] - 1 * $radius * cos ($dRadians))
      foreach ([$gray_gc, 5], [$black_gc, 0]);
}

sub DrawPointAt {
    my ($pixmap, $black_gc, $gray_gc, $nHour, $cx, $cy) = @_;
    my $dRadians = $nHour * $PI / 30;

    $pixmap->draw_point ($black_gc,
			$cx + 95/100 * $radius * sin ($dRadians),
			$cy - 95/100 * $radius * cos ($dRadians))
}