#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Spreadsheet::ParseExcel;
use LaTeX::Encode;
use Template;
use Data::Printer;

# excel => latex
my %fieldmap = (
    spellname => 'name',
    name => 'name',
    ability => 'name',
    level => 'level',
    equiv => 'level',
    school => 'scuola',
    source => 'source',
    uses => 'uses',
    type => 'type',
    comp => 'components',
    ct => 'tempo',
    at => 'tempo',
    range => 'range',
    target => 'target',
    duration => 'durata',
    st => 'st',
    sr => 'sr',
    description => 'descrizione',
    special => 'specialcomp',
    page => 'ref',
    notes => 'note',
);

my ($input_filename,$output_filename)=@ARGV;

die "$0 \$input \$output\n"
    unless $input_filename && $output_filename;

my $parser = Spreadsheet::ParseExcel->new();
my $wb = $parser->parse($input_filename)
    or die $parser->error;

sheet_2_latex(
    sheet_name => 'Incantesimi',
    output_filename => "${output_filename}.incantesimi.tex",
);
sheet_2_latex(
    sheet_name => 'Domini',
    sheet_idx => 1,
    output_filename => "${output_filename}.domini.tex",
    skip_col => 1,
);
sheet_2_latex(
    sheet_name => 'Abilità speciali',
    sheet_idx => 2,
    output_filename => "${output_filename}.special.tex",
    command => 'potere',
    skip_col => 1,
);

{
my $template;
sub template {
    $template //= do {local $/;<DATA>};
    return $template;
}
}

sub sheet_2_latex {
    my %opts = (
        sheet_idx => 0,
        fieldmap => \%fieldmap,
        command => 'incantesimo',
        @_,
    );

    my $spells = parse_table(
        $wb->worksheet($opts{sheet_name})
            // $wb->worksheet($opts{sheet_idx}),
        $opts{skip_col},
    );

    munge($spells);

    my $template = Template->new();
    $template->process(
        \template(),
        {
            spells => $spells,
            fieldmap => $opts{fieldmap},
            command => $opts{command},
            lt => \&latexise,
        },
        $opts{output_filename},
    )
    or die $template->error;
}

sub parse_table {
    my ($ws,$skip_col) = @_;
    $skip_col //= 0;

    my ($min_col,$max_col) = $ws->col_range();
    my ($min_row,$max_row) = $ws->row_range();
    my @headings = map { eval { $ws->get_cell($min_row,$_)->value } }
        $min_col .. $max_col;

    for my $h (@headings) {
        $h =~ s{^spell\W}{}i;
        $h =~ s{\W.*$}{};
        $h = lc($h);
    }

    my @ret = ();

    for my $row ((1+$min_row) .. $max_row) {
        # allow and skip empty rows
        next unless eval { $ws->get_cell($row,$min_col+$skip_col)->value };
        my %record;

        keys @headings;
        while (my ($idx,$heading) = each @headings) {
            # allow and skip empty cols
            next unless $heading;
            $record{$heading} =
                eval { $ws->get_cell($row,$idx+$min_col)->value } // '';
        }
        push @ret,\%record;
    }
    return \@ret;
}

sub munge {
    my ($spells) = @_;

    for my $spell (@$spells) {
        if ($spell->{page} =~ m{^\d+$}) {
            $spell->{page} = 'PHB'.$spell->{page};
        }
    }
    return;
}

sub latexise {
    my ($str) = @_;

    $str = latex_encode($str);
    $str =~ s{(?<!\\)\. }{.\\ }g;

    return $str;
}

__DATA__
\input{incantesimi.cmd}
\usepackage{textcomp}

\begin{document}
%
\begin{tikzpicture}
\matrix {

[% FOREACH spell IN spells %]
\[% command %]{
[%- FOREACH field IN fieldmap; IF spell.item(field.key) != '' %]
    [% field.value %]={[% lt(spell.item(field.key)) %]},
[%- END; END %]
} [% IF (loop.count() % 6) %]& [% ELSE %] \\ [% END -%]
[% IF (loop.count() % 18) == 0 %]};
\end{tikzpicture}

\pagebreak

\begin{tikzpicture}
\matrix {

[% END; END;
   rest_in_row = spells.size % 6;
   FOREACH skip IN [ 1 .. rest_in_row ]; ' & '; END; ' \\\\ '
%]};
\end{tikzpicture}
\vspace{-10pt}
\end{document}
