#!/usr/bin/perl -w

use strict;
use MGA::Advisories;
use Template;
use YAML qw(LoadFile DumpFile);
use File::Basename;

my %actions = (
    initqaconf => {
        run   => \&initqaconf,
        descr => 'Initialize configuration for QA team members',
        usage => <<END,
$0 initqaconf

Initialize a default configuration for QA team members, and open an
editor on the file.
END
    },
    list   => {
        run   => \&listadv,
        descr => 'List advisories',
        usage => <<END,
$0 list [filter...]

Print the list of published advisories. Optionally you can filter the
list with one or more filters. Possible filters are :
- advisory type
- distribution release
- package name
- CVE
- media

Examples :
 
 list advisories for package wireshark :
 \$ mgaadv list wireshark

 list security advisories for package wireshark :
 \$ mgaadv list security wireshark

 list advisories for CVE CVE-2013-3560
 \$ mgaadv list CVE-2013-3560

 list advisories for Mageia 2 in media tainted :
 \$ mgaadv list 2 tainted

END
    },
    mksite => {
        run   => \&mksite,
        descr => 'Generates the advisories web site',
        usage => <<END,
$0 mksite

Generates the advisories web site
END
    },
    process => {
        run   => \&process,
        descr => 'Process advisories',
        usage => <<END,
$0 process

Process advisories i.e. move the [S]RPMs, update website, send emails
END
    },
    new    => {
        run   => \&newadv,
        descr => 'Create a new advisory file',
        usage => <<END,
$0 new [type] [bugnum] [name]

Create a new advisory file. [type] should be security or bugfix,
[bugnum] is the bugzilla bug number and [name] is the package name.
END
    },
    nextid  => {
        run   => \&nextid,
        descr => 'Print next available ID',
        usage => <<END,
$0 nextid [type]

Print the next unused advisory ID for [type].
END
    },
    publish => {
        run => \&publish,
        descr => 'Assign an ID to an advisory file',
        usage => <<END
$0 publish [bugnum]

Assign a new ID to an advisory file.
END
    },
    'publish-all' => {
        run => \&publishall,
        descr => 'Publish all pending advisories',
        usage => <<END
$0 publish-all

Assign a new ID to all pending, validated advisories (subject to cross checks).
END
    },
    show   => {
        run   => \&showadv,
        descr => 'Show an advisory',
        usage => <<END,
$0 show [ID]

Show an advisory.
END
    },
    showjson   => {
        run   => \&showadvjson,
        descr => 'Show an advisory in JSON format',
        usage => <<END,
$0 showjson [ID]

Show an advisory in JSON format.
END
    },
    update => {
        run   => \&updateadv,
        descr => 'Update the advisories database',
        usage => <<END,
$0 update

Update the advisories database.
END
    },
    usage  => {
        run   => \&usage,
        descr => 'Show usage informations for an action',
        usage => <<END,
$0 usage [action]

Show action usage
END
    },
);

sub usage {
    if ($_[1] && $actions{$_[1]}) {
        print STDERR $actions{$_[1]}->{usage};
    } else {
        print STDERR "$0 [action] [options]\n";
        print STDERR "$0 usage [action]\n\n";
        print STDERR "Available actions:\n";
        print STDERR map { " - $_ : $actions{$_}->{descr}\n" } keys %actions;
    }
}
sub usageexit {
    usage(@_);
    exit 1;
}

sub mksite {
    my %advdb;
    $advdb{advisories} = MGA::Advisories::get_advisories();
    MGA::Advisories::publish_advisories(\%advdb);
    MGA::Advisories::sort_advisories(\%advdb);
    MGA::Advisories::output_pages(\%advdb);
    MGA::Advisories::dumpdb(\%advdb);
    MGA::Advisories::send_adv_mail(\%advdb);
    MGA::Advisories::send_report(\%advdb);
}

sub process {
    my %advdb;
    $advdb{advisories} = MGA::Advisories::get_advisories();
    MGA::Advisories::move_packages(\%advdb);
    MGA::Advisories::publish_advisories(\%advdb);
    MGA::Advisories::sort_advisories(\%advdb);
    MGA::Advisories::output_pages(\%advdb);
    MGA::Advisories::dumpdb(\%advdb);
    MGA::Advisories::send_adv_mail(\%advdb);
    MGA::Advisories::close_bugs(\%advdb);
    MGA::Advisories::send_report(\%advdb);
}

sub editor { $ENV{EDITOR} || $ENV{VISUAL} || '/usr/bin/editor' }

sub newadv {
    usageexit('usage', $_[0]) unless @_ == 4;
    my ($new, $type, $bugnum, $name) = @_;
    my $file = MGA::Advisories::newadv($type, $bugnum, $name);
    if ($file) {
        system(editor, $file);
    }
}

sub nextid {
    usageexit('usage', $_[0]) unless @_ == 2;
    my $type = $_[1];
    if (!$MGA::Advisories::config->{advisory_types}{$type}) {
        print STDERR "Unknown type $type\n";
        exit 1;
    }
    print MGA::Advisories::next_id(
        $MGA::Advisories::config->{advisory_types}{$type}{prefix},
        keys %{MGA::Advisories::get_advisories()}), "\n";
}

sub publish {
    usageexit('usage', $_[0]) unless @_ == 2;
    MGA::Advisories::assign_id($_[1]);
}

sub publishall {
    usageexit('usage', $_[0]) unless @_ == 1;
    MGA::Advisories::assign_ids();
}

sub listadv {
    shift;
    my %advdb;
    $advdb{advisories} = MGA::Advisories::get_advisories();
    MGA::Advisories::sort_advisories(\%advdb) if @_;
    MGA::Advisories::listadv(\%advdb, @_);
}

sub showadv {
    usageexit('usage', $_[0]) unless @_ == 2;
    my $adv = $_[1];
    my %advdb;
    $advdb{advisories} = MGA::Advisories::get_advisories();
    MGA::Advisories::showadv(\%advdb, $adv);
}

sub showadvjson {
    usageexit('usage', $_[0]) unless @_ == 2;
    my $adv = $_[1];
    my %advdb;
    $advdb{advisories} = MGA::Advisories::get_advisories();
    MGA::Advisories::showadvjson(\%advdb, $adv);
}

sub updateadv {
    usageexit('usage', $_[0]) unless @_ == 1;
    MGA::Advisories::download_advisories;
}

sub initqaconf {
    my $c = $MGA::Advisories::home_config_file;
    if (-f $c) {
        print STDERR "File $c already exists\n";
        exit 1;
    }
    my %defaultconf = (
        mode           => 'qa',
        out_dir        => $ENV{HOME} . '/mageia-advisories/html',
        status_dir     => $ENV{HOME} . '/mageia-advisories/status',
        advisories_dir => $ENV{HOME} . '/mageia-advisories/advisories',
    );
    DumpFile($c, \%defaultconf);
    system(editor, $c);
    my $newconf = LoadFile($c);
    foreach my $n ('out_dir', 'status_dir', 'advisories_dir') {
        mkdir dirname($newconf->{$n}) unless -d dirname($newconf->{$n});
    }
    foreach my $n ('out_dir', 'status_dir') {
        mkdir $newconf->{$n} unless -d $newconf->{$n};
    }
    if (! -d $newconf->{advisories_dir}) {
        system('svn', 'co', $MGA::Advisories::config->{advisories_repo_url},
            $newconf->{advisories_dir});
    }
}

if (@ARGV == 0 || !$actions{$ARGV[0]}) {
    usageexit();
}
$actions{$ARGV[0]}->{run}->(@ARGV);

