#!/usr/bin/env perl
# Make a pom.xml for using Zanata.

=pod

=head1 NAME

B<zanata_pom_xml_make> - Make a pom.xml for using Zanata

=head1 SYNOPSIS

B<zanata_pom_xml_make> -h | --help

B<zanata_pom_xml_make> [options] E<lt>pom.xmlE<gt>

=head1 DESCRIPTION
Make a pom.xml for using Zanata.

It either creates a new pom.xml or update an existing pom.xml with
Zanata plugin, Zanata pluginRepositories,
and Zanata maven plugin version.

The original file will be backed up with '.bak' by default.

=head1 ARGUMENTS

=over 4

=item pom.xml

pom.xml to be processed.

=back

=head1 OPTIONS

By default, if none of the options '-m', '-k' are defined,
E<lt>srcDirE<gt> and E<lt>transDirE<gt> will be added to E<lt>configureE<gt>.

However, this behavior is not performed if at least one of the mentioned options are specified.

=over 4

=item B<-h, --help>:

Print brief help message and exits.

=item B<-e, --excludes=PATTERN>

Insert a file exclude pattern as E<lt>excludesE<gt>I<PATTERN>E<lt>/excludesE<gt> to E<lt>configureE<gt>

=item B<-i, --includes=PATTERN>

Insert a file include pattern as E<lt>includesE<gt>I<PATTERN>E<lt>/includesE<gt> to E<lt>configureE<gt>

=item B<-k, --skip>

Insert a E<lt>skipE<gt>I<true>E<lt>/skipE<gt> to E<lt>configureE<gt>

=item B<-m, --enableModules>

Insert a E<lt>enableModulesE<gt>I<true>E<lt>/enableModulesE<gt> to E<lt>configureE<gt>

=item B<-s, --srcDir=DIR>

Set the source directory by
insert a E<lt>zanata.srcDirE<gt>I<DIR>E<lt>/zanata.srcDirE<gt> to E<lt>propertiesE<gt>.
Usually this is a directory that contains .pot files.
Either an absolute path or related to the pom.xml

Default is '.'.


=item B<-t, --transDir=DIR>

Set the translation directory by
insert a E<lt>zanata.transDirE<gt>I<DIR>E<lt>/zanata.transDirE<gt> to E<lt>propertiesE<gt>.
Usually this is a directory that contains .po files.
Either an absolute path or related to the pom.xml

Default is '.'.

=item B<-o, --backupSuffix=STRING>

Set the suffix for backup file.

Default is '.bak'

=item B<-p, --noPluginRepostories>

Do not insert Zanata pluginRepositories.

=back

=head1 FILES

=item zanata.cfg

Configure file for this program.
Directories will be visited in following order:
'~/.config', '/etc', 'etc' and '.'


See 'man zanata_pom_xml_make' for more infomation.
=cut

# Ensure it runs on RHEL5
use 5.008_008;
use strict;
use File::Basename;
use File::Spec;
use File::Copy;
use File::Find::Rule;
use Getopt::Long;
use Pod::Usage;
use XML::Twig::XPath;
#use Data::Dumper;
use lib "lib";
use Zanata::Util;

# path variables
my $scriptDir=dirname($0);

# Definition
my $cfgFilename="zanata.cfg";
my @cfgFileSearchPaths=( "$ENV{'HOME'}/.config", '/etc', 'etc', '.');

## Parse options
my $help=0;
my %optH=(
    'help' => '\$help'
    , 'noPluginRepostories' => 0
    , 'backupSuffix' => '.bak'
);

GetOptions(\%optH,
    , 'help|h'
    , 'excludes|e=s'
    , 'includes|i=s'
    , 'skip|k'
    , 'enableModules|m'
    , 'srcDir|s=s'
    , 'transDir|t=s'
    , 'backupSuffix|o=s'
    , 'noPluginRepostories|p'
) or pod2usage(-1);

### Display help
pod2usage(1) if $help;
pod2usage( {-verbose=>1}) if @ARGV == 0;

my %confH=();
my $isAutoAddDir=1;

for my $k (keys %optH){
    if ($k eq "excludes"){
	$confH{$k}=$optH{$k};
    }elsif($k eq "includes"){
	$confH{$k}=$optH{$k};
    }elsif($k eq "skip"){
	$confH{$k}='true';
	$isAutoAddDir=0;
    }elsif($k eq "enableModules"){
	$confH{$k}='true';
	$isAutoAddDir=0;
    }
}

my $srcDir=($optH{'srcDir'}) ? $optH{'srcDir'} : '.';
my $transDir=($optH{'transDir'}) ? $optH{'transDir'} : '.';

my $pomXml=$ARGV[0];
my $twig;

# Subroutines

sub zanataPluginRepoElement_new{
    my ($id, $name, $url, $releases, $snapshots)=@_;
    my $zPRepoStr=<<END;
<pluginRepository>
    <id>$id</id>
    <name>$name</name>
    <url>$url</url>
    <releases>
	<enabled>$releases</enabled>
      </releases>
      <snapshots>
	<enabled>$snapshots</enabled>
      </snapshots>
</pluginRepository>
END

    return Zanata::Util::xml_element_new_xml($zPRepoStr);
}

## Ensure zanata properties are inserted
sub zanataPropertiesElement_insert{
    my $srcDirElt=Zanata::Util::build_xpath($twig, '/project/properties/zanata.srcDir', 'last_child');
    $srcDirElt->set_text($srcDir);

    my $transDirElt=Zanata::Util::build_xpath($twig, '/project/properties/zanata.transDir', 'last_child');
    $transDirElt->set_text($transDir);
}

## Ensure zanata element are inserted
sub zanataPluginElement_insert{
    my ($mvnPluginVersion)=@_;
    my ($zanataPluginsElt)=$twig->findnodes('/project/build/plugins');
    my ($zanataPluginElt)=$twig->findnodes('/project/build/plugins/plugin[groupId="org.zanata"]');

    unless ($zanataPluginElt){
	### Create a new zanata plugin element if not present
	$zanataPluginElt=$zanataPluginsElt->insert_new_elt('plugin');
	$zanataPluginElt->insert_new_elt(groupId => 'org.zanata');
	$zanataPluginElt->insert_new_elt(artifactId => 'zanata-maven-plugin');
    }

    ## Update version
    Zanata::Util::xml_element_ensure_child($zanataPluginElt, 'version', $mvnPluginVersion, 1);

    my $confElt=Zanata::Util::xml_element_ensure_child($zanataPluginElt, 'configuration', '', 1, 'last_child');
    $confElt->cut_children();

    for my $conf (keys %confH){
	Zanata::Util::xml_element_ensure_child($confElt, $conf, $confH{$conf}, 0, 'last_child');
    }
    if ($isAutoAddDir){
	Zanata::Util::xml_element_ensure_child($confElt, 'srcDir', '${zanata.srcDir}', 0, 'last_child');
	Zanata::Util::xml_element_ensure_child($confElt, 'transDir', '${zanata.transDir}', 0, 'last_child');
    }
    return $zanataPluginElt;
}

###########################################################
# Main program
#
my %projInfo={};
my $zanataUtil=Zanata::Util->init(\%projInfo);

$twig= XML::Twig::XPath->new( pretty_print=>'indented');

## Parses pom.xml if exists, and backup the original file
if ( -e "$pomXml"){
    copy($pomXml, "$pomXml$optH{'backupSuffix'}");
    ### Parse pom.xml
    $twig->parsefile("$pomXml");
}

## If /project/build/plugins does not exist
### build up the path
Zanata::Util::build_xpath($twig, '/project/build/plugins');

my $root=$twig->root;

## Ensure zanata plugin exist and version match ZANATA_MVN_PLUGIN_VER
zanataPluginElement_insert($zanataUtil->{'cfgVarH'}->{'ZANATA_MVN_PLUGIN_VER'});

zanataPropertiesElement_insert();

my @pluginRepos=split(/;/,$zanataUtil->{'cfgVarH'}->{'ZANATA_MVN_REPOS'});

## if  noPluginRepostories
if($optH{'noPluginRepostories'}){
    ### if /project/pluginRepositories  exists
    my $zanataPluginRepositoriesElt=$twig->root->first_child('pluginRepositories');
    if ($zanataPluginRepositoriesElt){
	#### Then Foreach repo
	for my $pluginRepo (@pluginRepos){
	    my $id=$zanataUtil->{'cfgVarH'}->{"${pluginRepo}_ID"};
	    my @zanataPluginRepositoryEltL= $twig->findnodes(qq(/project/pluginRepositories/pluginRepository[id="$id"]));
	    ##### Remove existing repo
	    for my $zpElt (@zanataPluginRepositoryEltL){
		$zpElt->cut_descendants();
		$zpElt->cut();
	    }
	}
	#### remove /project/pluginRepositories if no other repos
	$zanataPluginRepositoriesElt->cut() if $zanataPluginRepositoriesElt->children_count() == 0;
    }


## If noPluginRepostories =0
}else{
    ### build_xpath /project/pluginRepositories
    my $zanataPluginRepositoriesElt=Zanata::Util::build_xpath($twig, '/project/pluginRepositories');

    ### Foreach repo
    for my $pluginRepo (@pluginRepos){
	my $id=$zanataUtil->{'cfgVarH'}->{"${pluginRepo}_ID"};
	### Add repo if not already exists
	my @zanataPluginRepositoryL= $twig->findnodes(qq(/project/pluginRepositories/pluginRepository[id="$id"]));
	unless (@zanataPluginRepositoryL){
	    my $name=$zanataUtil->{'cfgVarH'}->{"${pluginRepo}_NAME"};
	    my $url= $zanataUtil->{'cfgVarH'}->{"${pluginRepo}_URL"};
	    ##### plugin repository element new
	    my $zPluginRepoElt=zanataPluginRepoElement_new("$id", "$name", "$url", 'true', 'true');

	    ##### insert to /project/pluginRepositories
	    $zPluginRepoElt->paste($zanataPluginRepositoriesElt);
	}
    }
}

## Complete top level properties.
## Note that we should not modify the top level properties if either
## 1) groupId exists and it is not "org.zanata"
## 2) artifactId exists and it is not "null"

unless($root->first_child('artifactId') and $root->first_child('artifactId')->text ne 'null'){
    unless($root->first_child('groupId') and $root->first_child('groupId')->text ne 'org.zanata'){
	unless($root->first_child('artifactId')){
	    $root->insert_new_elt(artifactId => "null" );
	}
	unless($root->first_child('groupId')){
	    $root->insert_new_elt(groupId => "org.zanata"  );
	}
	unless($root->first_child('modelVersion')){
	    $root->insert_new_elt(modelVersion => '4.0.0'  );
	}
	if($root->first_child('version')){
	    $root->first_child('version')->set_text(
		$zanataUtil->{'cfgVarH'}->{'ZANATA_MVN_PLUGIN_VER'});
	}else{
	    $root->insert_new_elt(
		version => $zanataUtil->{'cfgVarH'}->{'ZANATA_MVN_PLUGIN_VER'}  );
	}
    }
}


## Write the final output to pom.xml
$twig->print_to_file($pomXml);
