#!/usr/local/bin/perl -w
# $Id: intclock 2868 2007-07-01 07:17:14Z verthezp $
# $URL: file:///var/lib/svn/intclock/tags/R2_13/bin/intclock $
#___________________________________________________________________
#                            intclock
#
# International clock
#___________________________________________________________________

# Copyright (C) 2004-2007 by Peter Verthez

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.

# Written by Peter Verthez, <Peter.Verthez@advalvas.be>.
# Based on Jens-Ulrik Petersen's hsclock

use strict;
use diagnostics;
use Config;
use Intclock::Config;
use vars qw($VERSION);

$VERSION = sprintf("%d.%02d", q$URL: file:///var/lib/svn/intclock/tags/R2_13/bin/intclock $ =~ /R(\d+)_(\d+)/);

###############################################################################
#  Some file globals
###############################################################################

my $progname = "intclock";
my $aboutString = sprintf
    ("$progname v%.2f\nCopyright (C) 2004-2007 Peter Verthez",
     $VERSION);

Intclock::Config::init($progname);

###############################################################################
#  Command line option handling
###############################################################################

package Cmdline;

use Getopt::Long;
use vars qw($header $spec $footer);

sub init {
  my ($optionhdr, $optionspec, $optionftr) = @_;
  my %optval;
  $header = $optionhdr;
  $spec   = $optionspec;
  $footer = $optionftr;
  $Getopt::Long::autoabbrev = 0;
  $Getopt::Long::getopt_compat = 0;
  $Getopt::Long::order = $REQUIRE_ORDER;
  $Getopt::Long::ignorecase = 0;
  my $result = GetOptions(\%optval,
			  map { $_->[0] . $_->[1] } @$spec);
  return ($result ? \%optval : undef);
}

sub show_help {
  my @lines = ();
  my @maxcolwidth = (0, 0, 0);
  print STDERR "$header\n" if defined $header;
  foreach my $opt (@$spec) {
    my @optstring = split "\\|", $opt->[0];
    my $opttype   = $opt->[2];
    my $opthelp   = $opt->[3];
    my @line = (($optstring[1] ? "-$optstring[1] $opttype  " : "  "),
		($opttype ? "--$optstring[0]=$opttype  ":"--$optstring[0]  "),
		$opthelp);
    push @lines, \@line;
    foreach my $col (0..2) {
      my $len = length($line[$col]);
      $maxcolwidth[$col] = $len if $len > $maxcolwidth[$col];
    }
  }
  foreach my $line (@lines) {
    print STDERR "  ";
    foreach my $col (0..2){
      printf STDERR "%-${maxcolwidth[$col]}s", $line->[$col];
    }
    print STDERR "\n";
  }
  print STDERR "\n$footer\n" if defined $footer;
}

###############################################################################
#  Main program
###############################################################################

package main;

use Intclock::TZ;
use Intclock::UI;
use Intclock::UI_tty;
use Intclock::L10N;

my $optionhdr  = "Usage: $progname [OPTION...]";

my @optionspec =
    (["verbose",      "", "", "chatty output on stderr"],
     ["version|v",    "", "", "show version number"],
     ["help|h",       "", "", "show this message"],
     ["debug",        "", "", "debug output"],
     ["gui|g",        "=s", "", "GUI module to be used"],
     ["geometry",     "=s", "", "standard X geometry option (width and height are ignored)"],
     );

my $optionftr =
    "The --version and --help options exit the program immediately.\n\n" .
    "The configuration, including the timezones, is taken from the\n" .
    "configuration file $Intclock::Config::configfile if that file\n" .
    "is present, e.g. written by a previous run of the program.\n\n".
    "If there is no configuration file, the time in the local timezone\n".
    "is shown.\n";

sub migrate_config {
  my ($config) = @_;
  if ($config->{"zones"}) {
    my @zones;
    foreach my $zone (@{$config->{"zones"}}) {
      if (not ref $zone) {
	$zone = [ $zone, "" ];
      }
      push @zones, $zone;
    }
    $config->{"zones"} = \@zones;
    delete $config->{"gui"};
    delete $config->{"debug"};
  }
  if (exists $config->{"horizontal"}) {
    if (exists $config->{"columns"}) {
      $config->{"layout"} = [ "columns", $config->{"columns"} ];
      delete $config->{"columns"};
    }
    elsif ($config->{"horizontal"}) {
      $config->{"layout"} = [ "horizontal" ];
    }
    else {
      $config->{"layout"} = [ "vertical" ];
    }
    delete $config->{"horizontal"};
  }
}

my $optval;
my $config_optval;
my $cmdline_optval = Cmdline::init($optionhdr, \@optionspec, $optionftr);

my $requested_gui = $cmdline_optval->{"gui"};

my $language = Intclock::L10N->get_handle()
  || die "Can't find an acceptable language module!?!";

if (not $cmdline_optval or $cmdline_optval->{"help"}) {
  Cmdline::show_help();
  exit();
}
elsif ($cmdline_optval->{"version"}) {
  print STDERR "$aboutString\n";
  exit();
}
elsif (defined $requested_gui
       and not grep /^$requested_gui$/, @Intclock::Config::all_guis) {
  print STDERR "Supported GUI options are: @Intclock::Config::all_guis\n";
  exit();
}
else {
  my $gui_to_use = $Intclock::Config::gui;

  if (defined $requested_gui) {
    $gui_to_use = $requested_gui;
  }
    
  Intclock::TZ::init($gui_to_use eq "Gtk" ? undef : $language);
  
  $config_optval = Intclock::Config::load();
  migrate_config($config_optval);

  # Show local zone if no zones listed in the config file
  $config_optval->{"zones"}
    = [ [ (Intclock::TZ::get_timezone_names())[0], "Local" ] ]
      if ! $config_optval->{"zones"} or ! @{$config_optval->{"zones"}};
  # Layout is vertical if not in config file
  $config_optval->{"layout"} = [ "vertical" ]
      if ! $config_optval->{"layout"} or ! @{$config_optval->{"layout"}};
  $config_optval->{"format"} = '%a %d%n%H:%M:%S'
      if ! $config_optval->{"format"};
    
  my @existing_zones = ();
  foreach my $zone (@{$config_optval->{"zones"}}) {
    my ($zonename, $zonelabel) = @$zone;
    if (not Intclock::TZ::exists($zonename) and $zonelabel ne "Local") {
      print STDERR "Timezone $zonename not defined.\n";
    }
    else {
      push @existing_zones, $zone;
    }
  }
  $config_optval->{"zones"} = \@existing_zones;
  exit(1) if ! @{$config_optval->{"zones"}};
  Intclock::Config::save($config_optval);

  Intclock::UI::set_config($config_optval, $cmdline_optval);

  if (! $ENV{"DISPLAY"}) {
    Intclock::UI_tty::start($optval);
  }
  elsif ($gui_to_use eq "Gtk") {
    require Intclock::UI_gtk;
    Intclock::UI_gtk::start($config_optval, $progname, $aboutString, $language);
  }
  elsif ($gui_to_use eq "Gtk2") {
    require Intclock::UI_gtk2;
    my $geometry = $cmdline_optval->{"geometry"};
    if (not $geometry and $config_optval->{"position"}) {
      my ($x, $y) = @{$config_optval->{"position"}};
      $geometry = "+$x+$y";
    }
    Intclock::UI_gtk2::start($config_optval, $progname, $aboutString,
			     $language,
			     $geometry, $config_optval->{"position"});
  }
  else {
    print STDERR "Unknown GUI option: '$gui_to_use'\n";
  }
}
