#!/usr/bin/perl 

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell
use strict;
use warnings;

# no warnings 'utf8';
use Carp;
use IPC::Cmd qw( can_run run );
use Log::Log4perl qw(:no_extra_logdie_message);
use POSIX qw(strftime);
use Biber;
use Biber::Output::BBL;
use Biber::Utils;
use File::Spec;

#Don't remove the next line!
#<wrapper_snippet>---------------------------------

use Getopt::Long qw/:config no_ignore_case/;
my $opts = {};
GetOptions(
  $opts,
  'fastsort|f!', ## now the default
  'locale|l=s',
  'collate|C!', ## to sort with Unicode::Collate
  'collate_options|c=s',
  'mincrossrefs|m=s',
  'unicodebbl|U!',
  'unicodebib|u!',
  'inputenc|i=s',  ## TODO
  'bibencoding|e=s',
  'useprd|p!',
  'bibdata|d=s',
  'outfile|O=s',
  'output-directory=s',
  'configfile|g=s',
  'noconf',
  'allentries|a!',
  'validate|V!',
  'debug|D!',
  'trace|T!',
  'quiet|q',
  'nolog!',
  'onlylog!',
  'wraplines|w!',
  'help|h|?',
  'version|v'
  );

#--------------------------------------------------

use open IO => ':utf8';

our $VERSION = $Biber::VERSION;

die usage() if exists $opts->{'help'};

die version() if exists $opts->{'version'};

die usage() unless @ARGV;

#--------------------------------------------------

# we can give a list of datafiles as argument, so
# this option is passed as an anon array
if ($opts->{bibdata}) {
  $opts->{bibdata} = [ split /\s*,\s*/, $opts->{bibdata} ]
}

if ($opts->{collate}) {
  $opts->{fastsort} = 0
}

my $outdir;
my $biberlog = 'biber.log';

if ( defined $opts->{'output-directory'} ) {
  $outdir = $opts->{'output-directory'};
  $biberlog = File::Spec->catfile($outdir, $biberlog);
}

my $biber = Biber->new(%$opts);

# Setting the logging level of Log::Log4perl
my $LOGLEVEL;
if (Biber::Config->getoption('trace')) {
  $LOGLEVEL = 'TRACE'
} elsif (Biber::Config->getoption('debug')) {
  $LOGLEVEL = 'DEBUG'
} elsif (Biber::Config->getoption('quiet')) {
  $LOGLEVEL = 'ERROR'
} else {
  $LOGLEVEL = 'INFO'
}

my $LOGLEVEL_F;
if (Biber::Config->getoption('nolog')) {
  $LOGLEVEL_F = 'OFF'
} else {
  $LOGLEVEL_F = $LOGLEVEL
}

my $LOGLEVEL_S;
if (Biber::Config->getoption('onlylog')) {
  $LOGLEVEL_S = 'OFF'
} else {
  $LOGLEVEL_S = $LOGLEVEL
}

## TODO make Screen.Threshold optional: in some situations we'd like
#  to have debug msgs on the screen too!

# configuration "file" for Log::Log4perl
my $l4pconf = qq(
    log4perl.category.main                             = $LOGLEVEL, Logfile, Screen
    log4perl.category.screen                           = $LOGLEVEL_S, Screen
    log4perl.category.logfile                          = $LOGLEVEL_F, Logfile

    log4perl.appender.Logfile                          = Log::Log4perl::Appender::File
    log4perl.appender.Logfile.utf8                     = 1
    log4perl.appender.Logfile.filename                 = $biberlog
    log4perl.appender.Logfile.mode                     = write
    log4perl.appender.Logfile.layout                   = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.Logfile.layout.ConversionPattern = [%r] %F{1}:%L> %p - %m%n

    log4perl.appender.Screen                           = Log::Log4perl::Appender::Screen
    ## the following option sets a max level of INFO for the console:
    ## i.e. debug messages can only go to the log file
    log4perl.appender.Screen.Threshold                 = INFO
    log4perl.appender.Screen.stderr                    = 0
    log4perl.appender.Screen.layout                    = Log::Log4perl::Layout::SimpleLayout
);

Log::Log4perl::init(\$l4pconf) ;

# get the logger object
my $logger  = Log::Log4perl::get_logger('main') ;
my $screen  = Log::Log4perl::get_logger('screen');
my $logfile = Log::Log4perl::get_logger('logfile');

#=====================================================
# Parse aux file
#=====================================================

my $auxfile;
my $bblfile;

my $time_string = strftime "%a %b %e, %Y, %H:%M:%S", localtime;
$logfile->info("=== Biber version $VERSION");
$logfile->info("=== $time_string");

if (Biber::Config->getoption('debug')) {
  $screen->info("DEBUG mode: all messages are logged to '$biberlog'")
}

if ( $opts->{allentries} && $opts->{bibdata} ) {
  $bblfile = $opts->{bibdata}->[0];
  $bblfile =~ s/(?:\.(bib|xml|dbxml))?$/\.bbl/;
}
else {
  $auxfile = $ARGV[0] or croak usage();
  $auxfile .= '.aux' unless $auxfile =~ m/\.aux$/;
  if (Biber::Config->getoption('outfile')) {
    $bblfile = Biber::Config->getoption('outfile')
  } else {
    $bblfile = $auxfile;
    $bblfile =~ s/aux$/bbl/;
  }

  if (defined($opts->{'output-directory'})) {
    my ($volume, $directories, $file) = File::Spec->splitpath($bblfile);
    $bblfile = File::Spec->catfile($outdir, $file)
  }
  $biber->parse_auxfile($auxfile);
}

if (Biber::Config->getoption('trace')) {
  $logger->trace("\n###########################################################\n",
    "############# Dump of initial config object: ##############\n",
    Data::Dump::pp($Biber::Config::CONFIG), "\n",
    "############# Dump of initial biber object: ###############\n",
    $biber->_stringdump,
    "\n###########################################################")
}

  # Set the output class. Should be a subclass of Biber::Output::Base
  $biber->set_output_obj(Biber::Output::BBL->new());

#=====================================================
# Parse/query database
#=====================================================

foreach my $bib (@{ Biber::Config->getoption('bibdata') }) {

  # this uses "kpsepath bib" and File::Find to find $bib in $BIBINPUTS paths:
  $bib = bibfind($bib);

  if ($bib =~ /\.(?:db)?xml$/) {
    $logger->logcroak("File $bib does not exist!") unless -f $bib;
    ##DISABLED: $biber->parse_biblatexml( $bib )
    $logger->logcroak("Support for the BibLaTeXML format is not included in this version of Biber.\n",
                      "You can try (at your own risk) to pull the \"biblatexml\" branch of our git repo.")
  }
  elsif ($bib =~ /\.bib$/) {
    $logger->logcroak("File $bib does not exist!") unless -f $bib;
    $biber->parse_bibtex($bib)
  }
  else {
    $logger->logcroak("File $bib.bib does not exist!") unless -f "$bib.bib";
    $biber->parse_bibtex("$bib.bib");
  }
}

if (Biber::Config->getoption('trace')) {
  $logger->trace("\n###########################################################\n",
    "############# Dump of post-parse config object: ###########\n",
    Data::Dump::pp($Biber::Config::CONFIG), "\n",
    "############# Dump of post-parse biber object: ############\n",
    $biber->_stringdump,
    "\n###########################################################")
}

$biber->prepare;

if (Biber::Config->getoption('trace')) {
  $logger->trace("\n###########################################################\n",
    "############# Dump of final config object: ################\n",
    Data::Dump::pp($Biber::Config::CONFIG), "\n",
    "############# Dump of final biber object: #################\n",
    $biber->_stringdump,
    "\n###########################################################")
}

# Get reference to output object
my $bbloutput = $biber->get_output_obj;
# Set the output target
$bbloutput->set_output_target_file($bblfile);
# Write the output to the target
$bbloutput->output;

# display warnings/errors summary, like BibTeX's format
# unless in quiet mode
unless (Biber::Config->getoption('quiet')) {
  if (defined($biber->{errors})) { # if errors, ignore warnings
    if ($biber->{errors} == 1) {
      print "(There was 1 error message)\n";
    } elsif ($biber->{errors} > 1) {
      print "(There were ", $biber->{errors}, " error messages)\n";
    }
  } elsif (defined($biber->{warnings})) {
    if ($biber->{warnings} == 1) {
      print "(There was 1 warning)\n";
    } elsif ($biber->{warnings} > 1) {
      print "(There were ", $biber->{warnings}, " warnings)\n";
    }
  }
}

#======================================================

sub version {
  qq{
biber version: $VERSION
      \n}
}

sub usage {
  qq{
Usage:  biber file.aux
        Creates file.bbl

        biber -d foo.bib file.aux
        Creates file.bbl from entries in foo.bib and the datafiles
        listed in file.aux

        biber -d foo.bib,bar.bib -a
        Creates foo.bbl from all entries in foo.bib and bar.bib

Options:
  --help|-h              Show this help message.
  --version|-v           Display version number.
  --mincrossrefs|-m <n>  Set threshold for crossrefs.
  --fastsort|-f          Use Perl’s sort instead of Unicode::Collate for sorting (TRUE).
  --locale|-l [locale]   Set the locale to be used for sorting with built-in sort function.
  --collate|-C           Sort with Unicode::Collate instead of the built-in sort function.
  --collate_options|-c [options]
                         Options to pass to the Unicode::Collate object used for sorting
                         (default is 'level => 2, table => latinkeys.txt').
                         See "perldoc Unicode::Collate" for details.
  --useprd|-p            Parse with Parse::RecDescent instead of Text::BibTeX.
  --bibdata|-d <files>   Use <files> as bibliography databases (comma separated list).
  --outfile|-O <file>    Output to <file> instead of <basename>.bbl
                         <file> is relative to --output-directory, if set (absolute
                         paths in this case are stripped to filename only). <file> can
                         be absolute if --output-directory is not set.
  --output-directory <d> Files (bbl and log) are output to directory <d> instead
                         of the current directory.
  --configfile|-g <file> Use <file> as configuration file for Biber.
                         The default is the first file found among
                         "biber.conf" in the current directory, "\$HOME/.biber.conf",
                         or else the output of "kpsewhich biber.conf".
  --noconf               Don't look for a configfile
  --allentries|-a        Output all entries in the database.
                         (NB: this ignores the .aux file.)
  --unicodebib|-u        Assume bib file is UTF-8 and skip latex_decode.
  --unicodebbl|-U        Encode the bbl output in UTF-8.
  --bibencoding|-e [encoding]
                         Specify the encoding of the bib file(s). The bbl file
                         will also have this encoding when --unicodebbl is false.
                         See "perldoc Encode::Supported" for a list of supported encodings.
  --validate|-V          Schema validate both the <basename>.bcf biblatex control file
                         and the BibLateXML files (if used). Dies on validation error.
  --debug|-D             Turn on debugging for biber.
  --quiet|-q             Turn infos and warnings off.
  --nolog                Do not write any logfile.
  --onlylog              Do not write any message to screen.
  --wraplines|-w         Wrap lines in the bbl file.
    \n}
}

__END__

=pod

=encoding utf8

=head1 NAME

C<biber> - A bibtex replacement for users of biblatex

=head1 SYNOPSIS

biber [ { --bibdata | -d } database.{bib|xml|dbxml} ] [ --useprd | -p ]
      [ --mincrossrefs | -m ] [ [--collate|-C] | [ --fastsort | -f ] ]
      [ --unicodebib | -u ] [ --unicodebbl | -U ] [ --debug | -D ]
      [ { --outfile | -O } filename ] file.aux

biber --bibdata database --allentries [ --outfile filename ] [ ... ]

biber { --help | --version }

=head1 DESCRIPTION

C<biber> provides a replacement of the bibtex processor for users of biblatex.
Besides emulating the functionality of bibtex + biblatex.bst, it also supports ...

(REST TO BE WRITTEN)

=head1 AUTHOR

François Charette, C<< <firmicus at gmx.net> >>

=head1 BUGS

Please report any bugs or feature requests on our sourceforge tracker at
L<https://sourceforge.net/tracker2/?func=browse&group_id=228270>.

=head1 COPYRIGHT & LICENSE

Copyright 2009-2010 François Charette and Philip Kime, all rights reserved.

This program is free software; you can redistribute it and/or
modify it under the terms of either:

=over 4

=item * the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any
later version, or

=item * the Artistic License version 2.0.

=back

=cut

# vim: set tabstop=2 shiftwidth=2 expandtab:
