#!/usr/local/bin/perl

# AUTHOR: Don Owens <don@regexguy.com>
# OWNER: 2010 Don Owens <don@regexguy.com>
# LICENSE: Perl_5

use strict;
use warnings;
use Carp;
use Getopt::Long qw(:config no_ignore_case bundling);

use Pod::POM::View::Restructured;

our $VERSION = '1.000003'; # VERSION

# main
{
    # local($SIG{__DIE__}) = sub { &Carp::confess };
    my $self = bless { }, __PACKAGE__;

    my $opts = $self->get_options([ "help|h",
                                    "in_file|infile|in-file|i=s",
                                    "out_file|outfile|out-file|o=s",
                                    "title=s",
                                  ], { });
    $self->check_options($opts, [ ]); # die's on bad options
    $self->{opts} = $opts;

    my ($in_fh, $out_fh) = $self->open_files;

    my $conv = Pod::POM::View::Restructured->new;
    my $output = $conv->convert_file($in_fh, $opts->{title}, $out_fh);

    unless (defined($output)) {
        print STDERR "\n\nFailed to convert!\n\n";
        exit 1;
    }

    exit 0;
}

exit 0;

###############################################################################
# Subroutines

sub open_files {
    my ($self) = @_;
    my $opts = $self->{opts};

    my $in_fh;
    my $out_fh;

    if (defined($opts->{in_file})) {
        open($in_fh, '<', $opts->{in_file})
            or die "couldn't open input file $opts->{in_file}: $!";
    }
    else {
        $in_fh = \*STDIN;
    }

    if (defined($opts->{out_file})) {
        open($out_fh, '>', $opts->{out_file})
            or die "couldn't open output file $opts->{out_file}: $!";
    }
    else {
        $out_fh = \*STDOUT;
    }

    return ($in_fh, $out_fh);
}

########## begin option processing ##########
sub print_usage {
    print STDERR qq{\nUsage: @{[ ($0 =~ m{\A.*/([^/]+)\Z})[0] || $0 ]} options

    Options:
        --infile         # filename for the pod to convert (input taken from
                         # stdin by default)
        --outfile        # filename for the resulting reStructuredText file
                         # (output sent to stdout by default)
        --title          # title for the document (by default an attempt will
                         # be made to extract the title, assuming that the first
                         # section is a head1 called NAME)
        [-h | --help]    # this help msg
\n};
}

sub check_options {
    my ($self, $opts, $required) = @_;

    if (not $opts or $opts->{help}) {
        $self->print_usage;
        exit 1;
    }

    my $opt_ok = 1;
    $required = [ ] unless $required;
    foreach my $key (@$required) {
        if (defined($opts->{$key})) {
            if (my $v = $opts->{$key}) {
                if (my $ref = ref($v)) {
                    if ($ref eq 'ARRAY' ) {
                        unless (@$v) {
                            $opt_ok = 0;
                            warn "missing required option '$key'
";
                        }
                    }
                }
            }
        }
        else {
            $opt_ok = 0;
            warn "missing required option '$key'\n";
        }
    }

    unless ($opt_ok) {
        $self->print_usage;
        exit 1;
    }

    return $opt_ok;
}

sub get_options {
    my ($self, $spec, $defaults) = @_;
    my %opts = $defaults ? %$defaults : ();
    $spec = [ ] unless $spec;

    my $process_opt = sub {
        my ($key, $val) = @_;

        if (scalar(@_) > 2) {
            $opts{$key}{$val} = $_[2];
        }
        else {
            if ( exists($opts{$key}) and (my $v = $opts{$key}) ) {
                if (my $ref = ref($v)) {
                    if ($ref eq 'ARRAY' ) {
                        push @{ $opts{$key} }, $val;
                        return 1;
                    }
                }
            }

            $opts{$key} = $val;
        }
    };

    my $opt_rv = Getopt::Long::GetOptions(map { ($_ => $process_opt) } @$spec);

    return $opt_rv ? \%opts : undef;
}
########## end option processing ##########

__END__

=pod

=head1 NAME

pod2rst - convert .pod files to .rst files

=head1 SYNOPSIS

=for pod2rst next-code-block: bash

pod2rst --infile=<name> --outfile=<name> --title=<name>

=head1 DESCRIPTION

Converts files containing POD to reStructuredText format for input to Sphinx.

=head1 ARGUMENTS

C<pod2rst> takes the following arguments:

=over 4

=item infile

 --infile=<name>

Specifies the pod file to convert.  Input is taken from stdin by default.

=item outfile

 --outfile=<name>

Specifies the reStructuredText file to create.  Output goes to stdout by default.

=item title

 --title=<title>

Specifies the section title for the file.

=back

=head1 SEE ALSO

L<Pod::POM::View::Restructured>, L<pod2html>

Sphinx: L<https://www.sphinx-doc.org/>

=head1 AUTHOR

Don Owens <don@regexguy.com>

=head1 COPYRIGHT

This software is copyright (c) 2010 by Don Owens <don@regexguy.com>.

This software is available under the same terms as the perl 5 programming language system itself.

=head1 VERSION

1.000003

=cut