#!/usr/bin/env perl
use warnings;
use strict;
use v5.10.0;

my $char;
my $layer;
my $ok = 1;

line:
while (<>) {
    s{\R\z}{};
    if (m{^\s*startchar:\s*(.*?)\s*$}i) {
        if (defined $char) {
            checkChar();
        }
        $char = {
            charName => $1,
            filename => $ARGV,
            lineNumber => $.,
            lines => [$_],
        };
        $char->{toString} = $char->{charName};
    } elsif (defined $char) {
        if (m{^\s*encoding:(?:\s+(\d+))?(?:\s+(\d+))?(?:\s+(\d+))?\s*$}i) {
            push(@{$char->{lines}}, $_);
            my @encoding = ($1, $2, $3);
            # first in the current font,
            #     then in unicode,
            #     and finally the original position (GID)
            $char->{encoding} = \@encoding;
            $char->{toString} .= sprintf(' (%d %d %d)', @encoding);
        } elsif (m{^\s*width:\s*(\d+)\s*$}i) {
            push(@{$char->{lines}}, $_);
            my $width = $1;
            $char->{width} = $1;
            if ($width != 1024) {
                printf("WWW %s: width is %d, should be 1024\n",
                       $char->{toString},
                       $char->{width});
            }
        } elsif (m{^\s*endchar\s*$}i) {
            push(@{$char->{lines}}, $_);
            checkChar();
            $char = undef;
        } elsif (m{^\s*back\s*$}i) {
            push(@{$char->{lines}}, $_);
            $layer = $char->{back} = {
                referenceCount => 0,
                splinesetCount => 0,
            };
        } elsif (m{^\s*fore\s*$}i) {
            push(@{$char->{lines}}, $_);
            $layer = $char->{fore} = {
                referenceCount => 0,
                splinesetCount => 0,
            };
        } elsif (defined $layer && m{^\s*refer:}i) {
            push(@{$char->{lines}}, $_);
            $layer->{referenceCount} += 1;
            # printf("\t\t%s: add a reference\n", $char->{toString});
        } elsif (defined $layer && m{^\s*splineset\s*$}i) {
            push(@{$char->{lines}}, $_);
            push(@{$char->{lines}}, "...");
            $layer->{splinesetCount} += 1;
            # printf("\t\t%s: add a splineset\n", $char->{toString});
            while (<>) {
                s{\R\z}{};
                if (m{^\s*endsplineset\s*$}i) {
                    push(@{$char->{lines}}, $_);
                    next line;
                }
            }
            goto eof;
        } else {
            push(@{$char->{lines}}, $_);
        }
    }
}
eof:

checkChar();

exit(!$ok);

sub checkChar {
    if (defined $char) {
        my $back = $char->{back};
        my $fore = $char->{fore};
        my $codepoint = $char->{encoding}->[1];
        if (defined $codepoint) {
            if ($codepoint >= 0x2800 && $codepoint < 0x2900) {
                # Braille
                return;
            }
        }
        if (defined $fore && defined $back) {
            if ($fore->{splinesetCount} && $back->{splinesetCount} &&
                    !$back->{referenceCount} && !$fore->{referenceCount}) {
                return;
            }
            if ($back->{referenceCount} && !$back->{splinesetCount}
                    && $fore->{splinesetCount} && !$fore->{referenceCount}) {
                printf("RRR %s: references should be moved to Fore layer\n",
                       $char->{toString});
                $ok = 0;
                return;
            }
            if ($fore->{referenceCount} && $back->{splinesetCount}) {
                # contains both references and background-layer splines
                return;
            }
        }
        if (!defined $fore && !defined $back) {
            return;
        }
        if (defined $fore && !defined $back) {
            if ($fore->{splinesetCount} && !$fore->{referenceCount}) {
                if ($codepoint >= 9600 && $codepoint < 9632) {
                    return;
                }
                printf("BBB %s: **may** need to be converted to Back layer with stroke\n", $char->{toString});
                return;
            }
            if ($fore->{referenceCount} && !$fore->{splinesetCount}) {
                return;
            }
            if (!$fore->{referenceCount} && !$back->{referenceCount}) {
                printf("    %s: likely just a space\n",
                       $char->{toString});
                return;
            }
        }
        printf("??? %s\n",
               $char->{toString});
        foreach my $line (@{$char->{lines}}) {
            printf("\t%s\n", $line);
        }
    }
}
