#!/usr/bin/env perl

use warnings;
use strict;

use FindBin;
use lib
    "$FindBin::Bin/../lib",
;

use Getopt::Long;

use Plerd;
use Plerd::Util;
use Plerd::Init;
use Cwd;
use Path::Class::Dir;

use Text::Wrap qw(wrap);

use Readonly;
Readonly my $DEFAULT_INIT_PATH => 'plerd';

my $webmention_enabled  = 0;
my $process_webmentions = 0;
my $rebuild_webmentions = 0;
my $config_file;
my $init_path;
GetOptions(
    'send-webmentions'    => \$webmention_enabled,
    'process-webmentions' => \$process_webmentions,
    'rebuild-webmentions' => \$rebuild_webmentions,
    'config=s'            => \$config_file,
    'init:s'              => \$init_path,
);

my $config_ref = Plerd::Util::read_config_file( $config_file );

if ( defined $init_path ) {
    my $is_using_default = 0;
    unless ( length $init_path ) {
        $init_path = Path::Class::Dir->new(
            cwd,
            $DEFAULT_INIT_PATH,
        )->stringify;
        $is_using_default = 1;
    }
    my $messages = Plerd::Init::initialize( $init_path, $is_using_default );
    print wrap( q{}, q{}, @$messages );
    print "\n";
    exit;
}

foreach (qw( base_uri image ) ) {
    unless ( ref $config_ref->{ $_ } ) {
        $config_ref->{ $_ } = URI->new ( $config_ref->{ $_ } );
    }
}

my $plerd = Plerd->new( $config_ref );

if ( $rebuild_webmentions ) {
    for my $post ( @{ $plerd->posts } ) {
        for my $wm ( values %{$post->webmentions_by_source} ) {
            $wm->verify;
            sleep 1;
        }
        $post->serialize_webmentions;
    }
}

my $new_webmentions_were_added;
if ( $process_webmentions ) {
    $new_webmentions_were_added = $plerd->webmention_queue->process;
}

# Proceed to republish all posts (and possibly send out webmentions) only if
# we're run without the "process-webmentions" flag, or we are processing
# received webmentions and found some new ones to publish.
unless ( $new_webmentions_were_added or !$process_webmentions ) {
    exit;
}

$plerd->publish_all;

if ( $webmention_enabled ) {
    print "Sending webmentions for all posts!\n";
    for my $post ( @{ $plerd->posts } ) {
        print $post->source_file . "...\n";
        my $report = $post->send_webmentions;
        print "$report->{attempts} attempts, "
              . "$report->{sent} sent, "
              . "$report->{delivered} delivered.\n";
    }
}

=head1 NAME

plerdall - Publish an entire Plerd blog from source

=head1 SYNOPSIS

In /path/to/plerd/conf/plerd.conf:

 base_uri: http://blog.example.com path: /home/me/Dropbox/plerd title:
 My Lovely Blog

And then, on the command line, while in the top-level plerd directory:

 bin/plerdall

Oh, you don't have a Plerd blog at all yet? Then you can try this first:

 bin/plerdall --init=/home/me/Dropbox/plerd

=head1 DESCRIPTION

Run in its default mode, this program directs Plerd to completely
publish a blog, once, based configuration. If the blog's already been
published, then it'll get wholly and freshly republished.

This program can perform other one-off Plerd-related tasks, as well, as
directed by command-line options provided to it. See L<"OPTIONS">,
below.

For instructions on installing and using Plerd, please see the README
file that should have accompanied this distribution. It is also
available online at L<https://github.com/jmacdotorg/plerd#plerd>.

=head1 OPTIONS

=head2 config

 bin/plerdall --config=/path/to/plerd.conf

Specify the location of a valid Plerd config file.

If not specified here, then this program will seek a config file in these
locations, and in this order:

=over

=item *

C<plerd.conf>, in the current working directory

=item *

C<conf/plerd.conf>, in the current working directory

=item *

C<.plerd>, in your home directory

=back

Consult the config file generated by C<plerdall --init> to learn more
about the config file format.

=head2 init

 bin/plerdall --init

 bin/plerdall --init=/path/to/new/plerd/directory

This command sets up a new working directory for a Plerd-powered blog.
It will contain default templates, workspaces, and config files.

If given a path, it will try to create the directory if one doesn't
already exist there. If the path already exists, plerdall will check
that it is an empty directory.

If not given a path, plerdall will default to C<./plerd>, and then
proceed as above.

This program will print either error text or a welcoming success message
with followup suggestions to STDOUT, and then exit. It will not perform
any blog publication beyond this initial setup.

=head1 EXPERIMENTAL OPTIONS

All of the following Webmention-related options are B<experimental>.

=head2 send-webmentions

 bin/plerdall --send-webmentions

After publishing all the blog's posts, Plerd will then
direct every post to scan itself for hyperlinks and attempt to send
webmentions to each one.

=head2 process-webmentions

 bin/plerdall --process-webmentions

Before publishing all the blog's posts, Plerd will
check to see if any new webmentions are waiting in its webmention-inbox.
If so, it will process those webmentions. Then, if at least one of those
received webmentions is valid, Plerd will republish all the blog's
posts. If neither of the prior conditions are true, Plerd will not
republish the blog.

This flag makes plerdall suitable for use as a scheduled task, via e.g.
cron.

=head2 rebuild-webmentions

 bin/plerdall --rebuild-webmentions

Before publishing all the blog's posts, Plerd will re-verify every valid
webmention that the blog has received and stored over its history,
overwriting its old webmention database with the results. Then it will
republish all the blog's posts.

The script rate-limits itself to one verification request per second, so
this might take a while.

This is a utility function intended for use if the serialization format
for Plerd's webmentions changes. You probably won't need to use it
often, if ever.

=head1 SEE ALSO

=over

=item *

L<Plerd>

=back

=head1 AUTHOR

Jason McIntosh <jmac@jmac.org>
