#!/usr/bin/perl

use strict;
use warnings;

use LWP::UserAgent ();
use Getopt::Long   ();
use YAML::Tiny     ();
use Data::Dumper;



my $config_file = "./update_cpanel-perl.config.yaml";
my $config = parse_config($config_file);

my $rpms = {};
my $no_of_rpms = 0;
my $arch = $config->{'arch'};
my $dist = $config->{'dist'};


# Describe packages we need
my @packages;
if (exists $config->{'packages'}) {
  @packages = @{ $config->{'packages'} };
}
else {
  @packages = qw{cpanel-perl.* cpanel-mariadb-native-client.*};
}

#Process cmd line options
my $verbose = 0;


Getopt::Long::GetOptions( 'verbose' => \$verbose,
                          'help'    => \&help,
);

if ( !defined $config->{'upstream_servers'} ) {
  die "You need to provide one or more upstream_servers in $config_file\n";
}
if( !defined $arch ) {
  die "You need to provide a target arch in $config_file\n";
}
if ( !$dist ) {
  die "You need to provide a target dist in $config_file\n";
}

my $ua = LWP::UserAgent->new;
$ua->timeout(5);

foreach my $upstream ( sort @{ $config->{'upstream_servers'} } ) {
  my $url = "http://$upstream/$arch/rpm.md5";
  print "Fetching upstream rpm list from $url\n" if $verbose;
  my $res = $ua->get( $url );
  if ( $res->is_success ) {
    my $content = $res->decoded_content;
    my @lines;
    foreach my $pkg ( @packages ) {
      push(@lines, grep(/$pkg/, split(/\n/, $content)) );
    }

    foreach my $line ( @lines ) {
      chomp($line);
      my ($md5, $rpm) = split(/\s+/, $line);
      my $untagged_rpm = $rpm;
      $untagged_rpm =~ s/\.cp11\d\d/\.$dist/;
      
      #Let's not add packages that are excluded in the config
      my $excluded = 0;
      foreach my $pkg ( @{ $config->{'exclude_packages'} } ) {
        $excluded = 1 if $untagged_rpm =~ m/$pkg/;
      }
      print "Excluding $untagged_rpm based on config\n" if $excluded && $verbose; 
      next if $excluded;

      $rpms->{"$untagged_rpm"} = { 'url' => "http://$upstream/$arch/$rpm" };
      $no_of_rpms++;
    }
  }
  else {
    warn "Couldn't GET upstream md5 list from $url\n";
  }
}

print "Number of unique rpms: " . keys($rpms) . "\n" if $verbose;
print "Number of rpms found: $no_of_rpms\n" if $verbose;

print "Looking for local cpanel rpms...\n" if $verbose;
opendir( my $dir_handle, $arch ) || die "Can't open $arch for reading $!\n";
while( readdir( $dir_handle ) ) {
  my $file = $_;
  my $found = 0;
  foreach my $pkg ( @packages ) {
    $found = 1 if $file =~ m/$pkg/;
  }
  next if ! $found;
  if( defined $rpms->{$file} ) {
    delete( $rpms->{$file} );
    print "Skipping $file as it already exists...\n" if $verbose;
  }
}
print "Done looking for local cpanel rpms\n" if $verbose;


if( scalar keys $rpms ) {

  print "Downloading new rpms...\n";
  foreach my $file ( keys $rpms ) {
    print "$file\n";
    my $res = $ua->get( $rpms->{$file}->{'url'} );
    if( $res->is_success ) {
      open( my $fh, '>', "$arch/$file" ) || die "Can't open $file for writing: $!\n";
      print $fh $res->content;
      close $fh;
    }
    else {
      warn "Couln't download " . $rpms->{$file}->{'url'} . ": $!\n";
    }
  }
  
  print "Done downloading rpms...\n";
  
  print "Please sign, run createrepo, and commit any new rpms, thanks!\n";
}
else {
  print "No new rpms, exiting...\n";
}


sub help {
  print <<"EOF";
Usage: $0 [--verbose] [--help]

This is a tool to download cpanel-perl-* RPMs from several upstream repos. It expects a ./update_cpanel-perl.config.yaml in your current working directory to specify the upstream sources.
You are required to provide the following options
 - upstream_servers: one or more urls to download from
 - arch: the arch you want do stage

Running the script will download all the cpanel-rpms and place the in your \\$arch directory. Afterwords you will need to sign the rpms, add and commit the rpms and metadata, and push to sync the rpms to the cip repo.

Example config:
---
  upstream_servers:
    - httpupdate.cpanel.net/RPM/11.46/centos/6
    - vmware-manager.dev.cpanel.net/RPM/11.46/centos/7
  arch: x86_64


EOF
  exit 0;
}

sub parse_config {
  my $config_file = shift;
  print "Using config $config_file" if $verbose;

  my $config = YAML::Tiny->read($config_file) || die "Couldn't read config file $config_file: $!\n";

  return $config->[0];
}
