#!perl
use strict;
use warnings;
use Getopt::Long;
use Filesys::Notify::Simple;
use Pod::Usage;

my @dir;
GetOptions(
    'dir=s@' => \@dir,
    'h|help' => \my $help,
) or pod2usage;
pod2usage(1) if $help;
@dir = ('.') unless @dir;

sub info {
    my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
        localtime(time);
    my $time = sprintf(
        "%04d-%02d-%02dT%02d:%02d:%02d",
        $year + 1900,
        $mon + 1, $mday, $hour, $min, $sec
    );

    print "[$time] ", join(' ', @_), "\n";
}

my $pid;

sub fork_and_start {
    my ( $server ) = @_;

    undef $pid;
    $pid = fork;
    die "Can't fork: $!" unless defined $pid;

    if ( $pid == 0 ) {      # child
        exec @ARGV;
        die "Cannot exec: @ARGV";
    }
}

sub kill_pid {
    $pid or return;

    info("Killing the existing server (pid:$pid)");

    kill 'TERM' => $pid;
    waitpid( $pid, 0 );
}

info("watching: @dir");
fork_and_start();
return unless $pid;

my $watcher = Filesys::Notify::Simple->new(\@dir);
while(1) {
    my @restart;
    $watcher->wait(sub {
        my @events = @_;
           @events = grep { valid_file($_) } map { $_->{path} } @events;
        @restart = @events;
    });
    next unless @restart;

    info("-- $_") for @restart;
    kill_pid();
    info("Successfully killed! Restarting the new server process.");
    fork_and_start();
    exit(0) unless $pid;
}

sub valid_file {
    my ($file) = @_;
    $file !~ m![/\\][\._]|\.bak$|~$|_flymake\.p[lm]!;
}

__END__

=encoding utf8

=head1 NAME

watcher - watch the file updates

=head1 SYNOPSIS

    % watcher --dir . -- osascript -e 'tell application "Google Chrome" to reload active tab of window 1'

        --dir=.     Diretory to watch.
        -h --help   show this help

=head1 DESCRIPTION

This command watches the directory updates, and run the commands.

=head1 AUTHOR

Tokuhiro Matsuno E<lt>tokuhirom AAJKLFJEF GMAIL COME<gt>

=head1 SEE ALSO

L<Filesys::Notify::Simple>

=head1 LICENSE

Copyright (C) Tokuhiro Matsuno

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

