#!/usr/bin/perl

use strict;
use lib qw(/usr/lib/libDrakX);
use c;
use common;
use standalone;
use Digest::MD5;
use network::netconnect;
use network::tools;

use Gtk2::TrayIcon;

use ugtk2 qw(:create :helpers :wrappers);
  
my ($eventbox, $img);
my ($menu, $timeout);
my $onstartupfile = "$ENV{HOME}/.net_applet";
add_icon_path("/usr/share/libDrakX/pixmaps/");
# Allow multiple instances, but only one per user:
is_running('net_applet') and die "net_applet already running\n";
my $prog_name = "/usr/bin/net_applet";
my $current_md5 = md5file($prog_name);

my %appletstate = (
             connected => {
  		          colour => [ 'connected' ],
			  changes => [ 'disconnected', 'error', 'busy' ],
			  menu => [ 'downNetwork', 'confNetwork', 'monitorNetwork', 'refresh', 'help' ],
			  tt => [ N_("Network is up on interface %s") ]
			  },
             disconnected => {
			      colour => [ 'disconnected' ],
			      changes => [ 'connected', 'error', 'busy' ],
			      menu => [ 'upNetwork', 'confNetwork', 'refresh', 'help' ],
			      tt => [ 
                            #-PO: keep the "Configure Network" substring synced with the "Configure Network" message below
                            N_("Network is down on interface %s. Click on \"Configure Network\"") 
                           ]
                             },
             notconfigured => {
  		          colour => [ 'disconnected' ],
			  changes => [ 'connected' ],
			  menu => [ 'confNetwork', 'refresh', 'help' ],
			  tt => [
                                 N_("You don't have any configured Internet connection.
Run the \"Add Connection\" assistant from the Mandrakelinux Control Center")
                                ]
			  }
	    );

my %actions = (
               'upNetwork' => { name => sub { N("Connect %s", $_[0]) }, launch => \&network::tools::start_interface },
               'downNetwork' => { name => sub { N("Disconnect %s", $_[0]) }, launch => \&network::tools::stop_interface },
               'monitorNetwork' => { name => N("Monitor Network"), launch => sub { system("/usr/sbin/net_monitor --defaultintf $_[0] &") } },
               'confNetwork' => { name => N("Configure Network"), launch => sub { system("/usr/sbin/drakconnect --skip-wizard &") } },
	       'refresh' => { name => N("Refresh"), launch => sub { checkNetwork() } },
               'help' => { name => N("Get Online Help"), launch => sub { system("drakhelp --id internet-connection &") } }
              );

gtkadd(my $icon = Gtk2::TrayIcon->new("Net_Applet"),
       gtkadd($eventbox = Gtk2::EventBox->new,
              gtkpack($img = Gtk2::Image->new)
             )
      );
$eventbox->signal_connect(button_press_event => sub {
			      if ($_[1]->button == 1) {
				  is_running('net_monitor') or netMonitor()
			      }
                              $_[1]->button == 3 && $menu and $menu->popup(undef, undef, undef, undef, $_[1]->button, $_[1]->time);
                          });
my ($opt) = @ARGV;
if ($opt eq '--force' || $opt eq '-f') { setAutoStart('TRUE') };

shouldStart() or die "$onstartupfile should be set to TRUE or use net_applet --force";

checkNetwork();
cronNetwork();

$icon->show_all;
Gtk2->main;

ugtk2::exit(0);

sub is_running {
    my ($name) = @_;
    any { !/^\s*$$\b/ && /\b\Q$name\E$/ } `ps -u $ENV{USER}`;
}
sub shouldStart() {
    my %p = getVarsFromSh($onstartupfile);
    my $ret = $p{AUTOSTART} eq 'FALSE' ? 0 : 1;
    $ret
}
sub md5file {
    my @md5;
    foreach my $file (@_) {
	open(my $FILE, $file) or do { print STDERR "Can't open '$file': $!"; push @md5, "" };
	binmode($FILE);
	push @md5, Digest::MD5->new->addfile($FILE)->hexdigest;
	close($FILE);
    }
    return wantarray() ? @md5 : $md5[0];
}
sub netMonitor() {
    system("/usr/sbin/net_monitor&");
    checkNetwork()
}
sub checkNetwork() {
    my $netcnx = {};
    my $netc = {};
    my $intf = {};
    network::netconnect::read_net_conf($netcnx, $netc, $intf);
    my ($gw_intf, $is_up, $gw_address, $dns_server) = network::tools::get_internet_connection($netc, $intf);
    go2State($gw_address ? 'connected' : $gw_intf ? 'disconnected' : 'notconfigured', $gw_intf);

    my $new_md5 = md5file($prog_name);
    if ($new_md5 ne $current_md5) { exec($prog_name) };
}
sub getIP {
    my ($interface) = shift;
    my $ifconfig = '/sbin/ifconfig';
    my @lines = `$ifconfig $interface`;
    my @ip = map { if_(/inet adr:([\d.]+)/, $1) } @lines;
    return wantarray() ? @ip : $ip[0];
}
sub cronNetwork() {
    $timeout = Glib::Timeout->add(5*1000, sub {
                                      checkNetwork();
                                      1;
                                  });
}
sub go2State {
    my ($state_type, $interface) = @_;
    $menu and $menu->destroy;
    $menu = setState($state_type, $interface);
}
sub setState {
    my ($state_type, $interface) = @_;
    my $checkmi;
    my $arr = $appletstate{$state_type}{menu};
    my $tmp = gtkcreate_pixbuf($appletstate{$state_type}{colour}[0]);
    $img->set_from_pixbuf($tmp);
    gtkset_tip(Gtk2::Tooltips->new, $eventbox, formatAlaTeX(common::sprintf_fixutf8(translate($appletstate{$state_type}{tt}[0]), $interface)));
    my $menu = Gtk2::Menu->new;
    foreach (@$arr) {
        my $name = ref($actions{$_}{name}) eq 'CODE' ? $actions{$_}{name}->($interface) : $actions{$_}{name};
        my $launch = $actions{$_}{launch};
        $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label($name)), activate => sub { $launch->($interface) }));
    }
    $menu->append(gtkshow(Gtk2::SeparatorMenuItem->new));
    $menu->append(gtksignal_connect(gtkset_active($checkmi = Gtk2::CheckMenuItem->new_with_label(N("Always launch on startup")), shouldStart()), toggled => sub { setAutoStart(uc(bool2text($checkmi->get_active))) }));
    $checkmi->show;
    $menu->append(gtksignal_connect(gtkshow(Gtk2::MenuItem->new_with_label(N("Quit"))), activate => sub { mainQuit() }));
    $menu
}
sub mainQuit() {
     Glib::Source->remove($timeout) if $timeout;
     Gtk2->main_quit
}
sub setAutoStart {
    my $state = shift;
    output_p $onstartupfile,
    qq(AUTOSTART=$state
);
}