#!/usr/bin/perl -w

# generate a .typ file and call gtypist to run this file
#
# Copyright (C) 2002 Yuusuke Mita <neiklotrrj@yahoo.com>,
#                    Stefan Troeger <stefan@troeger.st>
# Copyright (C) 2011-2020 Felix Natter <fnatter@gmx.net>
# Copyright (C) 2021, 2022, 2023 Felix Natter, Mihai Gătejescu
#
# 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

use strict qw (subs vars refs);
use Carp;
use File::Temp qw (tempfile);
use Getopt::Std;

# subroutines

# this creates a B:-command (centered on 66 columns because
# "gtypist <version>" is in the right corner)
sub getBanner($)
{
    my $banner = $_[0];
    # remove whitespace at the beginning ...
    $banner =~ s/^\s*//;
    # ... and at the end
    $banner =~ s/\s*$//;
    return "B:" . " " x (33 - int((length($banner) / 2))) . $banner . "\n";
}

my %opts;
if (!getopts ("dslhn:o:", \%opts) || $opts{h}) {
    print "SYNTAX: typefortune [-dslh] [-n count] [-o gtypist_opts]\n";
    print "-d: use D: (instead of S:)\n";
    print "-s: use fortune -s\n";
    print "-l: use fortune -l\n";
    print "-n <count>: practice <count> fortunes (default=1)\n";
    print "-o <gtypist_options>: pass options to gtypist\n";
    print "See the gtypist manual (info gtypist or info '(gtypist)') " .
	"for details.\n";
    if ($opts{h}) {
	exit 0;
    } else {
	exit 1;
    }
}

# operate on command-line arguments
my $exercise_type = "S:";
if ($opts{d}) { $exercise_type = "D:"; }
my $max_lines = 22;
if ($exercise_type eq "D:" || $exercise_type eq "d:") { $max_lines = 11; }
if ($opts{s} && $opts{l}) { die "-s and -l cannot be used together"; }
my $fortune_options = "";
if ($opts{s}) { $fortune_options .= " -s"; }
if ($opts{l}) { $fortune_options .= " -l"; }
my $count = 1;
if (defined ($opts{n})) { $count = $opts{n}; }

# create option-list for gtypist
my $gtypist_options = "";
if (!defined ($opts{o})) {
    # avoid warning
    $opts{o} = "";
}
foreach my $opt (split (/\s+/, $opts{o}))
{
    my $sepidx = index ($opt, ",");
    if ($sepidx == -1) {
	# boolean option
	if (length ($opt) == 1) { # short option
	    $gtypist_options .= "-" . $opt;
	} else { # long option
	    $gtypist_options .= "--" . $opt;
	}
    } else {
	# option with value
	if ($sepidx == 1) { # short option
	    $gtypist_options .= "-" . substr ($opt, 0, 1);
	} else { # long option
	    $gtypist_options .= "--" . substr ($opt, 0, $sepidx - 1);
	}
	$gtypist_options .= " " . substr ($opt, $sepidx + 1);
    }
    $gtypist_options .= " ";
}

my $i;
my $j;
my @lines;
my ($typfile, $typfilename);

eval {
  ($typfile, $typfilename) =
      tempfile("typefortune.XXXXXX", DIR => "/tmp", UNLINK => 1);
};
if ($@) {
  croak "Couldn't create temporary file in /tmp";
}

# note: $#lines is the index of the last line (and not the length of @lines)
print $typfile "# temporary file created by typefortune\n";
print $typfile "K:12:END\n";
for ($i = 0; $i < $count; $i++)
{
    {
        local $^W = 0;
        do {
            @lines = split (/\n/, `fortune$fortune_options`);
            die "Couldn't find fortune" unless $? == 0;
        } while ($#lines >= $max_lines);
    }

    # maybe insert banner
    if ($#lines > 0 && $lines[$#lines] =~ /^\s*-- (.+)\s*/) {
	print $typfile getBanner($1);
	pop @lines;
    } else {
	# clear any existing banner
	print $typfile "B:\n";
    }

    print $typfile "I:fortune ". ($i + 1) . "/" . $count . "\n";

    # print lines
    for ($j = 0; $j <= $#lines; $j++)
    {
	if ($j == 0) {
	    print $typfile "$exercise_type";
	} else {
	    print $typfile " :";
	}
	print $typfile $lines[$j];
	print $typfile "\n";
    }
}

print $typfile getBanner("Practice complete");
print $typfile "T:\n :\n :\n : Congratulations: " .
    "you successfully completed the $count " .
    "fortune lessons !\n";
print $typfile "*:END\nX:\n";
close($typfile) || die "Couldn't close $typfilename: $!";

# call gtypist
system("gtypist $gtypist_options $typfilename");
