#!/usr/bin/perl

###############################################################################
## Copyright (c) 2007-2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
###############################################################################

use strict;
use warnings;
use FindBin;
BEGIN { unshift @INC, "$FindBin::Bin/../www/perl-lib" }

use SMT::CLI;
use File::Basename;
use SMT::Utils;
use Digest::SHA1  qw(sha1 sha1_hex);

use Locale::gettext ();
use POSIX ();     # Needed for setlocale()

POSIX::setlocale(&POSIX::LC_MESSAGES, "");

if(!SMT::Utils::dropPrivileges())
{
    print STDERR __("Unable to drop privileges. Abort!\n");
    exit 1;
}

my $help = 0;

my @productids = ();
my $catalogid = "";
my $name = "";
my $description = "";
my $exturl = "";
my $target = "";
my @delete = ();

use Getopt::Long;
Getopt::Long::Configure( 'no_auto_abbrev');
my $optres = Getopt::Long::GetOptions(
                                      'productid=i'   => \@productids,
                                      'name=s'        => \$name,
                                      'description=s' => \$description,
                                      'exturl=s'      => \$exturl,
                                      'target=s'      => \$target,
                                      'delete=s'      => \@delete,
                                      'help|h'        => \$help
                                     );

if ( $help || !$optres )
{
    print 'smt-setup-custom-repos' . __(" : setup a custom repository\n");
    print "    --productid arg     " . __("Product id this repository belongs to.\n");
    print "                        " . __("You can use this option multiple times\n");
    print "                        " . __("to assign a repository to multiple products \n");
    print "    --name  arg         " . __("The name of this repository.\n");
    print "    --description arg   " . __("A description\n");
    print "    --exturl arg        " . __("The URL where this repository can be mirrored from\n");
    print "    --target arg        " . __("The target architecture of the repository\n");
    print "                        " . __("(only usefull when the product itself has no target architecture)\n");
    print "    --delete arg        " . __("Remove custom repository with the given ID. You can use this option multiple times.\n");
    print "                        " . __("Call 'smt repos --verbose' to find out the Repository ID\n");
    print "                        " . __("of the repository you want to delete.\n");
    print "\n\n";
    print __("Examples:\n\n");
    print "  smt-setup-custom-repos --productid 434 --name 'My_Repository' --exturl 'http://my.domain.top/My_Repository'\n";
    print "  smt-setup-custom-repos --delete 1cf336d819e8e5904f4d4b05ee081971a0cc8afc\n";

    exit 0;
}

my $dbh = SMT::Utils::db_connect();
if(!$dbh)
{
    die __("Cannot connect the database\n");
}

if(@delete > 0)
{
    my $statement = sprintf("SELECT ID, NAME, TARGET from Catalogs where ID IN ('%s')", join("','", @delete));
    my $arr = $dbh->selectall_arrayref($statement, {Slice=>{}});

    if(@{$arr} == 0)
    {
        print __("No catalogs found.\n");
        exit 1;
    }

    print __("Really delete the following repositories:\n");
    foreach my $entry (@$arr)
    {
        print " ".$entry->{ID}.":".$entry->{NAME};
        if(defined $entry->{TARGET})
        {
            print " ".$entry->{TARGET};
        }
        print "\n";
    }
    print __("[y/n] ");


    my $yn = <STDIN>;
    chomp($yn);
    $yn =~ s/^\s*//;
    $yn =~ s/\s*$//;

    if(lc($yn) eq __("y"))
    {
        my $removed = 0;
        foreach my $del (@delete)
        {
            $removed += SMT::CLI::removeCustomCatalog(catalogid => $del);
        }
        if(!$removed)
        {
            print __("No repository removed.\n");
            exit 1;
        }
        else
        {
            print __(sprintf("%d repositories removed.\n", $removed));
        }
    }
    else
    {
        print __("Nothing deleted.\n");
    }
    exit 0;
}

if($target ne "")
{
       my $targets_avail = $dbh->selectcol_arrayref("select distinct TARGET from Targets order by TARGET asc");
       my $found = 0;
       my $alltargets = "";
       foreach my $arch (@{$targets_avail})
       {
           if ($arch =~ /^$target$/i)
           {
               $target = $arch;
               $found = 1;
               last;
           }
       $alltargets .= $arch." ";
       }
       if ($found == 0)
       {
           print __("Unknown target architecture. Known architectures are:\n");
           print $alltargets."\n";
           exit 1;
       }
}

while($name !~ /^[a-zA-Z\d_-]+$/)
{
    if ($name) {
        print __("Invalid repository name. Allowed characters are characters, numbers, - and _\n");
    }

    print __("Repository Name:");
    $name = <STDIN>;
}
chomp($name);

while($exturl !~ /^(https?|file|ftp):\/\//)
{
    if ($exturl) {
        print __("Invalid URL. A http, https, ftp or file url is required.\n");
    }

    print __("URL:");

    $exturl = <STDIN>;
}
chomp($exturl);

if($description eq "")
{
    print __("Catalog description:");

    $description = <STDIN>;
}
chomp($description);

my $array = $dbh->selectall_arrayref("SELECT PRODUCTDATAID, PRODUCT, VERSION, REL, ARCH from Products where PRODUCT_LIST='Y' group by PRODUCT, VERSION, REL, ARCH",
                                     {Slice => {}});
my @validProductIds = ();
my $anotherone = 0;

if(@productids == 0 )
{
    print __("Select product where this repository belongs to.\n\n");

    foreach my $item (@{$array})
    {
        print $item->{PRODUCTDATAID}."\t";
        print $item->{PRODUCT}." ";
        print $item->{VERSION}." " if(defined $item->{VERSION});
        print $item->{REL}." " if(defined $item->{REL});
        print $item->{ARCH}." " if(defined $item->{ARCH});
        print "\n";

        push @validProductIds, $item->{PRODUCTDATAID};
    }
    print "\n";
}

while(@productids == 0 || $anotherone)
{
    print __("Product Number:");

    my $pid = <STDIN>;
    chomp($pid);

    if( !grep( ($_ eq $pid), @validProductIds) )
    {
        print __("Invalid Product Number.\n");
        next;
    }
    push @productids, $pid;

    print __("Select an additional product for this repository (y/n)?");
    my $yn = <STDIN>;
    chomp($yn);

    if(lc($yn) eq __("y"))
    {
        $anotherone = 1;
    }
    else
    {
        $anotherone = 0;
    }
}
$catalogid = sha1_hex($name);

my %options = (
               productids  => \@productids,
               catalogid   => $catalogid,
               name        => $name,
               description => $description,
               exturl      => $exturl,
               target      => $target
              );

my $success = SMT::CLI::setupCustomCatalogs( %options );
if($success)
{
    print __("Repository successfully added.\n");
    exit 0;
}
else
{
    print __("Adding repository failed.\n");
    exit 1;
}

#
# Manpage
#

=head1 NAME

smt setup-custom-repos

=head1 SYNOPSIS

smt [help|--help|-h] setup-custom-repos
smt setup-custom-repos --delete <repositoryid>
smt-setup-custom-repos --productid <product_id> --name <repository name> --exturl <url>

=head1 DESCRIPTION

The smt-setup-custom-repos script is a tool for setup custom repositories
(repositories not present in NU) to be used with SMT.
It can be used for adding a new repository to the SMT database or to delete a repository
from the database.


=head1 OPTIONS

=head2

=over

=item --productid <id>

ID of a product the repository belongs to. If the repository should belong to multiple
products, use this option multiple times to assign repository to all relevant products.

=item --name <repository name>

The name of the custom repository.

=item --description <description>

The description of the custom repository.

=item --exturl <url>

The URL where this repository can be mirrored from.

=item --target arg

The target architecture of the repository
(only usefull when the product itself has no target architecture)

=item --delete <Repository ID>

The command smt-setup-custom-repos --delete ID removes a
custom repository with a given ID from the SMT database.

Call B<smt repos --verbose> to find out the Repository ID of the repository
you want to delete.

=back

=head1 EXAMPLES

Configure a new custom repository:

 smt-setup-custom-repos --productid 431 --productid 432 --productid 433 --productid 434 --productid 435 \
 --name 'My_Repository' --exturl 'http://my.domain.top/My_Repository'


Remove the repository with the id I<1cf336d819e8e5904f4d4b05ee081971a0cc8afc>:

  smt-setup-custom-repos --delete 1cf336d819e8e5904f4d4b05ee081971a0cc8afc

=head1 AUTHORS and CONTRIBUTORS

Duncan Mac-Vicar Prett, Lukas Ocilka, Jens Daniel Schmidt, Michael Calmer

=head1 LICENSE

Copyright (c) 2007-2012 SUSE LINUX Products GmbH, Nuernberg, Germany.

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 of the License, 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., 675 Mass
Ave, Cambridge, MA 02139, USA.

=cut


