# -*- mode: Perl -*-
# /=====================================================================\ #
# |  authblk.sty.ltxml                                                  | #
# |=====================================================================| #
# | Part of LaTeXML:                                                    | #
# |  Public domain software, produced as part of work done by the       | #
# |  United States Government & not subject to copyright in the US.     | #
# |---------------------------------------------------------------------| #
# | Bruce Miller <bruce.miller@nist.gov>                        #_#     | #
# | http://dlmf.nist.gov/LaTeXML/                              (o o)    | #
# \=========================================================ooo==U==ooo=/ #
package LaTeXML::Package::Pool;
use strict;
use warnings;
use LaTeXML::Package;

# NOTE: preliminary implementation focusing on the logic;
# We currently don't layout the author/afflition block quite the way authblk does:
#  * don't combine authors with same affiliation,
#  * don't use marks to associate the author/affiliation

DefMacro('\Affilfont', '\normalfont');
DefMacro('\Authfont',  '\normalfont');
DefMacro('\Authsep',   ',');
DefMacro('\Authand',   ' and ');
DefMacro('\Authands',  ', and ');
DefMacro('\authorcr',  '\\\\\Authfont');

# package bookkeeping
DefConditional('\ifnewaffil');
DefRegister('\affilsep'  => Dimension('1em'));
DefRegister('\@affilsep' => Dimension('1em'));
NewCounter('Maxaffil');
SetCounter('Maxaffil', Number(2));
NewCounter('authors');
NewCounter('affil');
NewCounter('@affil');

DefMacro('\the@affil', 'affil\arabic{@affil}');
DefMacro('\author[]{}', sub {
    return map { Invocation(T_CS('\lx@ab@author'), $_[1], Tokens(@$_)) }
      SplitTokens($_[2], T_CS('\and'), T_OTHER(',')); });

DefMacro('\lx@ab@author[]{}',
  '\@add@frontmatter{ltx:creator}[role=author]'
    . '{\@personname{#2}\lx@split@authormark{#1}}');

# Preserve the order, where we add an "affiliationmark" element
# for each numeric mark in the \author[] optional argument
DefMacro('\lx@split@authormark{}', sub {
    if (my @marks = split(/\s*,\s*/, ToString($_[1]))) {
      return (map { T_CS('\lx@authormark'), T_OTHER($_) } @marks); }
    else {
      return (T_CS('\lx@authormark'), T_CS('\the@affil')); } });

DefConstructor('\lx@authormark{}',
  "^?#mark(<ltx:contact role='affiliationmark' _mark='#mark'></ltx:contact>)()",
  properties => sub { (mark => ToString($_[1])); });

DefConstructor('\affil[]{}',
  "^?#2(<ltx:note mark='#mark' role='affiliationtext'>#2</ltx:note>)()",
  afterDigest => sub {
    my ($stomach, $whatsit) = @_;
    my $mark = $whatsit->getArg(1);
    if (!defined $mark) {
      $mark = Digest(T_CS('\the@affil'));    # get mark
      StepCounter('@affil'); }               # and THEN step counter!
    $whatsit->setProperty(mark => ToString($mark));
    return; });

Tag('ltx:document', afterClose => \&authblkRelocateAffil);

sub authblkRelocateAffil {
  my ($document)   = @_;
  my @author_nodes = $document->findnodes(".//ltx:contact[\@role='affiliationmark' and \@_mark]");
  my @affil_nodes  = $document->findnodes(".//ltx:note[\@role='affiliationtext']");
  # first, unbind all affiliation text nodes - they get reparented or discarded.
  my %mark_to_affil = ();
  for my $affil_node (@affil_nodes) {
    $affil_node->parentNode->removeChild($affil_node);
    # if we get conflicting marks -- which we shouldn't
    # the last node wins
    if (my $mark = $affil_node->getAttribute('mark')) {
      $mark_to_affil{$mark} = $affil_node; } }
  # Now process all affiliationmarks
  for my $author_node (@author_nodes) {
    $author_node->setAttribute(role => 'affiliation');
    my $mark = $author_node->getAttribute('_mark') || '';
    if (my $affil_node = $mark_to_affil{$mark}) {
      $document->appendClone($author_node, $affil_node->childNodes); } }
  return; }

# we shouldn't need these, but if someone is using them low-level
# might as well provide them
DefMacro('\AB@authnote{}',  '\textsuperscript{\normalfont#1}');
DefMacro('\AB@affilnote{}', '\textsuperscript{\normalfont#1}');

#======================================================================
1;
