#!/usr/bin/perl -w
#
# This is part of ypp-sc-tools, a set of third-party tools for assisting
# players of Yohoho Puzzle Pirates.
#
# Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
# are used without permission.  This program is not endorsed or
# sponsored by Three Rings.

# This script helps make memmed or not memmed points visible.

my $usage= <<END;
usage:
   ypp-chart-memshow [/home/user/path/to/Desktop]
   ypp-chart-memshow /path/to/screenshot/to/convert.png
   ypp-chart-memshow - < /path/to/screenshot/to/convert.png
if given a Desktop directory will look for
   /home/user/path/to/Desktop/"Puzzle Pirates <Name> <number>".png
and delete them after display
END

use POSIX;
use strict qw(vars refs);
use File::Glob qw(:glob);

our $quis= $0;
$quis =~ s,.*/,,;


sub badusage ($) {
    print STDERR "bad usage: @_\n$usage\n";
    exit 8;
}

sub xglob ($) {
    my ($pat) = @_;
    my @glob= bsd_glob($pat, GLOB_ERR|GLOB_LIMIT|GLOB_NOSORT);
    die "$quis: error reading directory: $!\n" if GLOB_ERROR;
    return @glob;
}

sub synchronously ($) {
    my ($file) = @_;
    print "$quis: $file displaying...\n";
    open STDIN, "<", $file or die "$quis: $file: $!\n";
    synchronously_stdin();
}

sub synchronously_stdin () {
    exec 'bash', '-ec', '
        set -o pipefail
        pngtopnm |ppmchange -closeness 10 "#806c60" blue |display -
    ';
    die "$quis: bash: $!\n";
}

sub watch_dir ($) {
    my ($dir) = @_;
    chdir $dir or die "chdir $dir: $!";

    my %already;
    my $pat= "Puzzle Pirates *.png";
    $already{$_}='a' foreach xglob($pat);
    print "$quis: watching $dir...\n";
    if (!%already) {
	print "$quis: warning: no existing screenshots found\n";
    }
    my %children;
    for (;;) {
	select undef,undef,undef, 0.100;

	my $child;
	while (($child= waitpid -1, WNOHANG) > 0) {
	    my $file= $children{$child};
	    if (!defined $file) {
		die "$quis: unknown child $child failed status $?\n" if $?;
		warn "$quis: unknown child $child, finished ok\n";
	    } else {
		die "$quis: display of $file failed status $?\n" if $?;
		delete $already{$file};
		delete $children{$child};
		unlink $file or $!==&ENOENT
		    or die "$quis: delete $file: $!\n";
		print "$quis: $file deleted.\n";
	    }
	}

	my @extra= grep { !exists $already{$_} } xglob($pat);
	next if !@extra;
	die "$quis: multiple screenshots at once! (@extra)\n" if @extra>1;

	my $file= $extra[0];
	
	print "$quis: $file found...\n";
	my $lastsize= -1;
	for (;;) {
	    if (!stat $file) {
		next if $!==&ENOENT;
		die "$quis: check $file: $!\n";
	    }
	    my $size= (stat _)[7];
	    die "$quis: $file: not a plain file !\n" unless -f _;
	    next unless $size;
	    last if $size==$lastsize;
	    $lastsize= $size;
	    select undef,undef,undef, 0.300;
	}

	$child= fork;  defined $child or die $!;
	if (!$child) {
	    synchronously($file);
	    exit(0);
	}
	$children{$child}= $file;
	$already{$file}= $child;
    }
}


while (@ARGV && $ARGV[0] =~ m/^\-./) {
    $_= shift @ARGV;
    last if $_ eq '--';
    badusage("unknown option \`$_'");
}

our $target;

if (!@ARGV) {
    $target= $ENV{'HOME'};
    die unless defined $target;
    $target .= '/Desktop';
} elsif (@ARGV==1) {
    $target= shift @ARGV;
} else {
    badusage("at most one non-option argument please");
}

if ($target eq '-') {
    synchronously_stdin();
}

(stat $target) or die "$quis: cannot find $target: $!\n";

if (-f _) {
    synchronously($target);
} else {
    watch_dir($target);
}
