#!/usr/bin/perl

# libconf standalone binary

# Copyright (C) 2003-2005 Damien Krotkine (dams@libconf.net)
#
# 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; only version 2, no any other 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.

#we'll use this to understand command line options
use Getopt::Long;

#options setup
my ($help_arg, $action_arg, $if_arg, $of_arg, $template_arg, $list_template_arg, $list_template_options_arg);
$result = GetOptions("action=s" => \$action_arg,
                     "if=s" => \$if_arg,
                     "of=s"  => \$of_arg,
                     "template=s" => \$template_arg,
                     "template-options=s" => \$template_options_arg,
                     "list-templates" => \$list_template_arg,
                     "list-templates-options" => \$list_template_options_arg,
                     "xml-format=i" => \$xml_format_arg,
                     "help" => \$help_arg,
                    );

#print "DEBUG : [$action_arg] [$if_arg] [$of_arg] [$help_arg] [$list_template_arg] [$template_options_arg]\n";

# help -> usage
$help_arg and usage();
# list templates
if ($list_template_arg) {
    foreach (list_templates()) {
        my $a = $_; $a =~ s|/|::|g;
#        print "***********" . "require Libconf::Glueconf::$a; Libconf::Glueconf::$a" . "::description()" . "\n";
        print "$_ - " . eval (qq(require Libconf::Glueconf::$a; Libconf::Glueconf::$a) . qq(::description())) . "\n";
    }
    exit 0;
}
#if the options are not correct, we print usage and exit.
my $err_mesg = check_options();
$err_mesg and print ("\nERROR : $err_mesg \n\n"), usage();

if ($action_arg eq 'export_xml') {
    my $t = $template_arg;
    $t =~ s|/|::|g;
    my $template_class = "Libconf::Glueconf::$t";
    my $obj;
    my $xml;
    my $template_options = check_template_options($template_options_arg);
#    print "*************" . qq( require $template_class; import $template_class; \$obj = new $template_class({ filename => "$if_arg", $template_options }); ) . "\n";
    eval qq( require $template_class; import $template_class; \$obj = new $template_class({ filename => "$if_arg", $template_options }); );
    $of_arg eq '-' ? $obj->toXMLString() : $obj->toXMLFile($of_arg);
}

if ($action_arg eq 'import_xml') {
    my $t = $template_arg;
    $t =~ s|/|::|g;
    my $template_class = "Libconf::Glueconf::$t";
    my $obj;
    my $xml;
    my $template_options = check_template_options($template_options_arg);
#    print "*************" . qq( require $template_class; import $template_class; \$obj = new $template_class({ filename => "$if_arg", $template_options }); ) . "\n";
    eval qq( require $template_class; import $template_class; \$obj = new $template_class({ filename => "", $template_options }); );
    $if_arg eq '-' ? die 'not yet implemented, sorry :/': $obj->fromXMLFile($if_arg);
    $of_arg eq '-' ? die 'not yet implemented, sorry :/': $obj->write_conf($of_arg);
}





sub check_template_options {
    my ($template_options_arg) = @_;
    join (', ', map { my ($k, $v) = split(/:/, $_); qq($k => "$v"); } split(/,/, $template_options_arg));
}

sub list_templates {
    require Libconf::Glueconf;
    my $d = substr($INC{'Libconf/Glueconf.pm'}, 0, -3);
    map { (m|$d/(.*).pm|) } glob(substr($INC{'Libconf/Glueconf.pm'}, 0, -3) . "/*/*");
}

sub check_options {
    member($action_arg, qw(export_xml import_xml)) or return "bad action or no action specified.";
    member($template_arg, list_templates()) or return "bad or no template specified. Try --list-templates to get a list of templates";
    $if_arg eq '-' || -r $if_arg or return "input file [$if_arg] is not readable. Specify a correct input file with --if= ";
    $of_arg eq '-' || -w $of_arg or return "output file [$of_arg] is not writable. Specify a correct output file with --of= ";
    return 0;
}

sub usage {
    print qq(
Usage: libconf --action=[ACTION] --if=[INPUT-FILE] --of=[OUTPUT-FILE]
   or: libconf --help

Modify configuration files without losing any information or destroying anything.
see http://www.libconf.net

  --action \t\t\t the action to do, can be :
\t\t\t\t export_xml : output an xml equivalent of the config file
\t\t\t\t import_xml : use the input file as xml, and generate the config fil accordingly

  --if=<FILENAME> \t\t the input config file to work on. If set to - , data are read from STDIN
  --of=<FILENAME> \t\t the output config file to produce. If set to - , data are outputed to STDOUT

  --template=<TEMPLATE> \t the template that should be used to parse the config file (see list-templates)
  --list-templates \t\t lists the templates available
  --template-options=<OPTIONS> \t the options that you may need to pass to the template (see list-templates-options)
\t\t\t\t the options are a list of key value pair, seperated by comas. For instance : option1:value1,option2:value2
  --list-templates-options \t lists the options of a particular template (which you need to specify with --template)

  --xml-format : \t\t specify the optional indenting format of the output, can be 0, 1, 2
  --help \t\t\t prints this message

Ewamples
write an xml representation of /etc/passwd to /tmp/pass.xml :
libconf -action=export_xml -template=System/Passwd -if=/etc/passwd -of=/tmp/pass.xml

the reverse operation :
libconf -action=import_xml -template=System/Passwd -of=/tmp/passwd -if=/tmp/pass.xml

WARNING : for import/export-xml to work, you need to install Data::DumpXML and
Data::DumpXML::Parser from cpan or through your distribution
);

exit 0;
}

sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 }
