#!/usr/bin/perl -w
use strict; # $Id: mbutiny 123 2019-07-02 14:23:28Z abalama $

=head1 NAME

mbutiny - easily interact with App::MBUtiny from the command line

=head1 SYNOPSIS

    mbutiny [options] [commands [args]] 

    mbutiny [-dlv]

    mbutiny [--debug] [--log] [--config=CONFIG_FILE] [--datadir=DATADIR]
            [ configure | test [HOSTs] | backup [HOSTs] | 
            restore [HOSTs] [YYYY.MM.DD] | report ]

    mbutiny configure

    mbutiny test

    mbutiny backup

    mbutiny restore

    mbutiny report

=head1 OPTIONS

=over 4

=item B<-c CONFIG_FILE, --config=CONFIG_FILE>

Full path of the configuration file. The configuration file allows determine the 
basic default settings, which will use the system if it fails to specify additional 
configuration files in $CONFDIR directory. The default system 
path /etc/mbutiny/mbutiny.conf

=item B<-D DATADIR, --datadir=DATADIR, --dir=DATADIR>

The directory of temporary files.

Default: system temp directory

=item B<-d, --debug>

Enable debug mode. In this mode, debug messages are displayed on the screen

=item B<-h, --help>

Show short help information and quit

=item B<-H, --longhelp>

Show long help information and quit

=item B<-l, --log>

Enabling write debug information to syslog or user log file.

Do not confuse the debug logging from regular logging to a file mbutiny.log.
Regular logging allows you to store information in mbutiny.log on the progress of the processes 
module (test, backup, restore), whereas debug logging for debugging of the internal components 
of the module.

To control the level of debugging mbutiny.log see parameter LogEnable and LogLevel.

=item B<-v, --verbose>

Enabling at which displays information about the progress on the screen

=item B<-V, --version>

Print the version number of the program and quit

=back

=head1 COMMANDS

=over 4

=item B<configure>

Configure (initializing) the MBUtiny

=item B<test [HOSTs]>

Testing of HOSTs after configuration and before backup performing.

By default will used all enabled in configuration HOSTs.

=item B<backup [HOSTs]>

Compressing all the objects for the specified HOSTs and then send the resulting archive to 
the storage.

By default will used all enabled in configuration HOSTs.

=item B<restore [HOSTs] [DATE]>

Downloading the file from the storages previously created backup by name.
And then, each downloaded file is unpacked to the restore directory

By default will used all enabled in configuration HOSTs.

DATE - is date of backup in format: DD.MM.YYYY or YYYY.MM.DD

=item B<report [HOSTs]>

Checking the last backup-file on each available collector for all defined backup names

By default will used all enabled in configuration HOSTs.

=back

=head1 DESCRIPTION

Websites and any file system elements backup tool

See L<WWW::MLite> for details

=head1 AUTHOR

Serz Minus (Sergey Lepenkov) L<http://www.serzik.com> E<lt>abalama@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved

=head1 LICENSE

This program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

See L<https://dev.perl.org/licenses/>

=cut

use Getopt::Long;
use Pod::Usage;

use Cwd qw/getcwd/;
use File::Spec;

use CTK::FilePid;

use App::MBUtiny;

use constant {
    PIDMASK     => '%s.%s.pid',
    PIDREQS     => [qw/backup restore/],
};

$| = 1;  # autoflush

my $options = {};
Getopt::Long::Configure ("bundling");
GetOptions($options,
    # NoUsed keys map:
    #
    # a A b B   C     e E
    # f F g G     i I j J
    # k K   L m M n N o O
    # p P q Q r R s S   T
    # u U     w W x X y Y
    # z Z

    # Information and debug
    "help|usage|h",         # Show help page
    "longhelp|H|?",         # Show long help page
    "version|vers|ver|V",   # Print VERSION of the App::MBUtiny
    "debug|d",              # Debug mode
    "verbose|v",            # Verbose mode
    "log|l",                # Log mode
    "test|testmode|t",      # Test mode

    # CTK Application
    "config|conf|c=s",      # Config file
    "datadir|dir|D=s",      # DataDir

) || pod2usage(-exitval => 1, -verbose => 0, -output => \*STDERR);
pod2usage(-exitval => 0, -verbose => 1) if $options->{help};
pod2usage(-exitval => 0, -verbose => 2) if $options->{longhelp};
printf("Version: %s\n", App::MBUtiny->VERSION) && exit(0) if $options->{version};

# VARS
my $command = shift(@ARGV) || '';
my @arguments = @ARGV;

my ($pidfile, $pidstat);
$SIG{INT} = sub {
    print STDERR "Trying interrupt...\n";
    $ENV{SIG_INT} = $ENV{SIG_INT} ? ($ENV{SIG_INT}+1) : 1;
    $pidfile->remove if $pidfile;
    die "Abnormally interrupted\n" if $ENV{SIG_INT} >= 2;
};

# App::MBUtiny instance
my $app = new App::MBUtiny(
        project => PROJECTNAME,
        prefix  => PREFIX,
        ($options->{config} && -e $options->{config} ? (configfile => $options->{config}) : ()),
        ($options->{datadir} ? (datadir => $options->{datadir}) : ()),
        plugins => [qw/ archive /],
        options => $options,
        debug   => $options->{debug},
        verbose => $options->{verbose},
        log     => $options->{log},
        test    => $options->{test},
    );
pod2usage(-exitval => 1, -verbose => 99, -sections => 'SYNOPSIS|OPTIONS|COMMANDS', -output => \*STDERR)
    unless $command && grep {$_ eq $command} ($app->list_handlers());

if (grep {$_ eq $command} @{(PIDREQS())}) {
    $pidfile = new CTK::FilePid({
        file => File::Spec->catfile($app->tempdir(), sprintf(PIDMASK, PREFIX, $command))
    });
    $pidstat = $pidfile->running || 0;
}

if ($pidfile) {
    die(sprintf("Already running (%s, PID=%s)", $pidfile->file(), $pidstat)) if $pidstat;
    $pidfile->write;
}

# Run
my $exitval = $app->run($command, @arguments) ? 0 : 1;
printf STDERR "%s\n", $app->error if $exitval && $app->error;

$pidfile->remove if $pidfile;

exit $exitval;

1;

__END__
