#!/usr/bin/perl

use strict;
use File::Spec;

# Library path bootstrap
my @path;
if (defined $ENV{PAR_TEMP}) { # See PAR.pm
	@path = ($ENV{PAR_TEMP}, 'inc');
}
else {
	my $binary = File::Spec->rel2abs($0);
	my ($vol, $dirs, undef) = File::Spec->splitpath($binary);
	@path = ($vol, $dirs, File::Spec->updir);
}
my $libdir = File::Spec->catdir(@path, 'lib');
unshift @INC, $libdir if -d $libdir;

eval q{
	use File::BaseDir ();
	use Zim::Utils;
	use Zim;
};
die $@ if $@;

# i18n initialization
$Zim::CODESET = 'utf8';
$Zim::LANG = '';

for (qw/LC_ALL LC_MESSAGES LANGUAGE LANG/) {
	next unless $ENV{$_};
	$Zim::LANG = $ENV{$_};
	last;
}
$Zim::LANG =~ s/[\.\@].*//; # remove encoding / modifier
$Zim::LANG = '' if $Zim::LANG eq 'C' or $Zim::LANG eq 'POSIX';

eval {
	require I18N::Langinfo;
	I18N::Langinfo->import(qw(langinfo CODESET));
	$Zim::CODESET = langinfo(CODESET()) || 'utf8';
};
warn "No langinfo available. Defaulting to utf8\n" if $@;

# Data dir bootstrap
my $sharedir = File::Spec->catdir(@path, 'share');
if (-d $sharedir) {
	$ENV{XDG_DATA_DIRS} =
		join ':', $sharedir, File::BaseDir->xdg_data_dirs;
}

# Parse command line options
my $verbose = 1;
my $export;
my ($root, $page, $name, $pidfile, $type, $profile);
my (@geometry, $iconify);

while ($ARGV[0] =~ /^-/) {
	$_ = shift @ARGV;
	
	if (/^(--version|-v)$/) {
		print $Zim::LONG_VERSION;
		exit;
	}
	elsif (/^--quiet$/)        { $verbose = 0   }
	elsif (/^(--verbose|-V)$/) { $verbose = 2   }
	elsif (/^(--debug|-D)$/)   { $verbose = 3   }
	elsif (/^--doc$/) {
		($root) = grep {-d $_}
			map File::Spec->catdir($_, 'zim', 'doc'),
			File::BaseDir->xdg_data_dirs;
		$profile ||= 'reader';
	}
	elsif (/^--export$/)   { $export = shift @ARGV     }
	elsif (/^--name$/)     { $name = shift @ARGV       }
	elsif (/^--pidfile$/)  { $pidfile = shift @ARGV    }
	elsif (/^(--profile|-p)$/)  { $profile = lc shift @ARGV }
	elsif (/^--type$/)     { $type = shift @ARGV       }
	elsif (/^--geometry$/) { 
		my $g = shift @ARGV;
		$g =~ /^(\d+)[xX](\d+)(?:\+(\d+)\+(\d+))?$/
			or die "$0: --geometry needs argument of form wxh[+x+y]\n";
		@geometry = ($1, $2, $3, $4);
	}
	elsif (/^--iconify$/)  { $iconify = 1 }
	elsif (/^--?\w/)       { exit_usage() } # includes --help etc.
	
	last if /^--?$/;
}

$SIG{__WARN__} = sub {
	return if $verbose == 0; # no messages at all
	my ($lvl, $error) = (1, shift);
	$lvl += length $1 if $error =~ /^(#+)\s/;
	print STDERR $error, @_ unless $lvl > $verbose;
};

warn "# This is zim $Zim::VERSION\n" if $verbose > 1;
warn "# locale: $Zim::LANG.$Zim::CODESET\n";

# Load messages
Zim::Utils::find_translation();

# Write pidfile
if (defined $pidfile) {
	if (open PID, '>', $pidfile) {
		print PID "$$\n";
		close PID;
	}
	else { warn "Could not write pidfile: $pidfile\n" }
}

# Find Notebook
unless (defined $root) { # for example: zim --doc pagename
	if (@ARGV) {
		exit_usage() if @ARGV > 2;
		$root = shift @ARGV;
		if ($root =~ '/') {
			exit_not_found($root) unless -d $root;
		}
		else { # notebook name
			$name = $root;
			$root = Zim->get_notebook($name);
			exit_not_found($name) unless defined $root;
		}
	}
	elsif (defined $name) {
		$root = Zim->get_notebook($name);
		exit_not_found($name) unless defined $root;
	}
	else {
		$root = Zim->get_default_notebook();	
	}
}
else { exit_usage() if @ARGV > 1 }
$page = shift @ARGV;

# Export
if ($export) {
	eval q{use Zim::Selection};
	die $@ if $@;
	die "$0: export needs a notebook\n" unless defined $root;
	my %opts = map split('=', $_, 2), split ',', $export;
	my $o = {
		resolve => 1,
		recurse => defined($opts{recurse}) ? $opts{recurse} : 1
	};
	my @pages = grep defined($_), ($page, @ARGV);
	@pages = (':') unless @pages;
	my $rep = Zim->new( 
		dir => $root,
		type => $type,
		name => $name,
	);
	my $s = Zim::Selection->new($rep, $o, @pages);
	$s->export(\%opts);
	exit 0;
}

# Load GUI modules
eval q/
	use Gtk2 -init;
	use Zim::GUI;
/;
die $@ if $@;

if ($verbose > 1) {
	my $compiled = join '.', Gtk2->GET_VERSION_INFO;
	my $linked   = join '.', Gtk2->get_version_info;
	warn   "# Gtk2 version is $Gtk2::VERSION\n",
	       "#   compiled against gtk+ $compiled\n",
	       "#   linked   against gtk+ $linked\n" ;
	warn defined($root)
	     ? "# Notebook name = $name\n"
	     . "#          dir  = $root\n"
	     . "#          type = $type\n"
	     . "#          page = $page\n"
	     : "# No notebook defined\n"   ;
}

# Start GUI
if (defined $root) { show_GUI($name, $root, $type, $page) }
else { 
	eval 'use Zim::GUI::NotebookDialog;';
	die $@ if $@;
	Zim::GUI::NotebookDialog->new()->show(\&show_GUI);
}

Gtk2->main;

unlink $pidfile if defined $pidfile;
exit;

sub show_GUI {
	my ($name, $root, $type, $page) = @_;

	#warn "root: $root\n";

	# Initialize application object
	my $zim;
	eval {
		$zim = Zim::GUI->new(
			profile => $profile,
			dir => $root,
			type => $type,
			name => $name,
			pidfile => $pidfile,
		);
	};
	if ($@) {
		Zim::GUI::Component->error_dialog($@);
		unlink $pidfile if defined $pidfile;
		exit 3;
	}

	# Initialize application window
	$zim->gui_init;

	if ($page) {
		eval { $zim->JumpTo($page) };
			# dies when page does not exist in read-only mode
		warn $@ if $@;
	}

	$zim->gui_show;
	if (@geometry) {
		warn "# Geometry @geometry\n";
		$zim->{window}->resize(@geometry[0,1]);
		$zim->{window}->move(@geometry[2,3]) if @geometry > 2;
	}
	if ($iconify) { # TODO: move into gui_show to prevent flashing of the window
		$zim->{hide_on_delete}
			? $zim->hide : $zim->iconify ;
	}
}

sub exit_usage {
	print STDERR << "EOT";
Usage: $0 [OPTIONS] [NOTEBOOK] [PAGE]

  NOTEBOOK is the directory to store all docs, for example ~/zim/
           or the name of an earlier configured notebook
  PAGE     is the page you want to open

  See man zim(1) for OPTIONS, try "$0 --doc" for the user manual
EOT
	unlink $pidfile if defined $pidfile;
	exit 1;
}

sub exit_not_found {
	print STDERR ( ($_[0] =~ m#/#)
		? "$0: No such directory: $_[0]\n"
		: "$0: No such notebook: $_[0]\n" );
	exit 2;
}

1;

__END__

=head1 NAME

zim - A desktop wiki and outliner

=head1 SYNOPSIS

B<zim> [I<OPTIONS>] [I<NOTEBOOK> [I<PAGE>]]

=head1 DESCRIPTION

B<Zim> is a desktop wiki writtin in perl using Gtk2.

Try to execute C<zim --doc> to view the user manual.

=head1 OPTIONS

=over 4

=item B<--doc>

Open the zim documentation.

=item B<--export> I<OPTIONS>

Export pages to another format. OPTIONS should at least
contain 'dir' and 'format', and optionally 'template',
and 'media'.

Example:

	zim --export dir=./html,format=html ./Wiki

This will export all pages in the notebook dir "./Wiki"
to a dir "./html" using the html format.

=item B<-p>, B<--profile> I<NAME>

Open using a certain profile. For example use C<-p reader>
to open a notebook read-only.

=item B<--type> I<NAME>

Give the type for a new notebook.

=item B<--pidfile> I<FILE>

Write the process id of to I<FILE>.

=item B<--geometry> I<W>xI<H>[+I<X>+I<Y>]

Set the size of the main window to I<W>xI<H> pixels
and position the window at I<X>,I<Y>.

=item B<--iconify>

Start zim iconified. If the TrayIcon plugin is enabled
this option will start zim in the system tray.

=item B<--quiet>

Do not print any information to the terminal.

=item B<-V>, B<--verbose>

Print more verbose information to the terminal.

=item B<-D>, B<--debug>

Print developer information to the terminal.

=item B<-v>, B<--version>

Print version and copyright information and quit.

=back

=head1 AUTHOR

Jaap Karssenberg E<lt>pardus@cpan.orgE<gt>

Copyright (c) 2005, 2007 Jaap G Karssenberg. All rights
reserved. This program is free software; you can redistribute it and/or
modify it under the same terms as Perl.

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

=head1 SEE ALSO

L<Zim>(3)

=cut
