The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!perl
use strict;
use warnings;
use autodie;

use Getopt::Long;
use Pod::Simple::HTML;

sub main {
    my ( $help, $type, $html );
    GetOptions(
        'type:s' => \$type,
        'html'   => \$html,
        'help'   => \$help,
    );

    if ($help) {
        print <<'EOF';
make-rmg-checklist [--type TYPE]

This script creates a release checklist as a simple HTML document. It accepts
the following arguments:

  --type    The release type for the checklist. This can be BLEAD-FINAL,
            BLEAD-POINT, MAINT, or RC. This defaults to BLEAD-POINT.

  --html    Output HTML instead of POD

EOF

        exit;
    }

    $type = _validate_type($type);

    open my $fh, '<', 'Porting/release_managers_guide.pod';
    my $pod = do { local $/; <$fh> };
    close $fh;

    my $heads = _parse_rmg( $pod, $type );
    my $new_pod = _munge_pod( $pod, $heads );

    if ($html) {
        my $simple = Pod::Simple::HTML->new();
        $simple->output_fh(*STDOUT);
        $simple->parse_string_document($new_pod);
    }
    else {
        print $new_pod;
    }
}

sub _validate_type {
    my $type = shift || 'BLEAD-POINT';

    my @valid = qw( BLEAD-FINAL BLEAD-POINT MAINT RC );
    my %valid = map { $_ => 1 } @valid;

    unless ( $valid{ uc $type } ) {
        my $err
            = "The type you provided ($type) is not a valid release type. It must be one of ";
        $err .= join ', ', @valid;
        $err .= "\n";

        die $err;
    }

    return $type;
}

sub _parse_rmg {
    my $pod  = shift;
    my $type = shift;

    my @heads;
    my $include = 0;
    my %skip;

    for ( split /\n/, $pod ) {
        if (/^=for checklist begin/) {
            $include = 1;
            next;
        }

        next unless $include;

        last if /^=for checklist end/;

        if (/^=for checklist skip (.+)/) {
            %skip = map { $_ => 1 } split / /, $1;
            next;
        }

        if (/^=head(\d) (.+)/) {
            unless ( keys %skip && $skip{$type} ) {
                push @heads, [ $1, $2 ];
            }

            %skip = ();
        }
    }

    return \@heads;
}

sub _munge_pod {
    my $pod   = shift;
    my $heads = shift;

    $pod =~ s/=head1 NAME.+?(=head1 SYNOPSIS)/$1/s;

    my $new_pod = <<'EOF';
=head1 NAME

Release Manager's Guide with Checklist

=head2 Checklist

EOF

    my $last_level = 0;
    for my $head ( @{$heads} ) {
        my $level = $head->[0] - 1;

        if ( $level > $last_level ) {
            $new_pod .= '=over ' . $level * 4;
            $new_pod .= "\n\n";
        }
        elsif ( $level < $last_level ) {
            $new_pod .= "=back\n\n" for 1 .. ( $last_level - $level );
        }

        $new_pod .= '=item * ' . 'L<< /' . $head->[1] . " >>\n\n";

        $last_level = $level;
    }

    $new_pod .= "=back\n\n" while $last_level--;

    $new_pod .= $pod;

    return $new_pod;
}

main();