# -*- mode: Perl -*-
# /=====================================================================\ #
# |  acronym                                                            | #
# | Implementation for LaTeXML                                          | #
# |=====================================================================| #
# | 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;

#======================================================================
DefMacro('\acsfont{}',  '#1');
DefMacro('\acffont{}',  '#1');
DefMacro('\acfsfont{}', '#1');

DefConditional('\ifAC@footnote');
DefConditional('\ifAC@nohyperlinks');
DefConditional('\ifAC@printonlyused');
DefConditional('\ifAC@withpage');
DefConditional('\ifAC@smaller');
DefConditional('\ifAC@dua');    # dua = don't use acronmyms
DefConditional('\ifAC@nolist');
DefConditional('\ifAC@starred');

DefMacro('\AC@placelabel{}', '');
#======================================================================
# Whether an acronym is used or not
DefPrimitive('\lx@AC@used{}', sub {
    AssignValue('ACROUSED@' . ToString($_[1]) => 1, 'global'); });
DefPrimitive('\AC@logged{}', sub { });    # ???

DefMacro('\acused{}',      '\AC@logged{#1}');
DefMacro('\acronymused{}', '\AC@logged{#1}');
DefMacro('\acresetall',    '');                 # ????

DefMacro('\lx@AC@if{}{}{}', sub {
    my ($gullet, $id, $short, $long) = @_;
    my $key = 'ACROUSED@' . ToString($_[1]);
    if (LookupValue($key)) {
      $short->unlist; }
    else {
      AssignValue($key => 1, 'global');
      $long->unlist; } });

#======================================================================
# Acronyms in the Text

# NOTE: replacement of acronyms (short, long, whatever) should EXCLUDE \acroextra
# BUT those should be present in an acronym list!
# Acronym lists can (optionally) only include the acronyms actually used in the text!

# \lx@acronym{acronym}{listname}{showform}
DefConstructor('\lx@acronym Undigested {}{}{}',
  "<ltx:glossaryref key='#2' inlist='#3' show='#4'/>",
  reversion => '#1{#2}');

DefMacro('\AC@acs{}',  '\lx@acronym{\acs}{#1}{acronym}{short}');
DefMacro('\AC@acl{}',  '\lx@acronym{\acl}{#1}{acronym}{long}');
DefMacro('\AC@acsp{}', '\lx@acronym{\acsp}{#1}{acronym}{short-plural}');
DefMacro('\AC@aclp{}', '\lx@acronym{\aclp}{#1}{acronym}{long-plural}');
DefMacro('\AC@acsi{}', '\lx@acronym{\acsi}{#1}{acronym}{short-indefinite}');
DefMacro('\AC@aclI{}', '\lx@acronym{\aclI}{#1}{acronym}{long-indefinite}');

# Short form
DefMacro('\acs OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acsa');
DefMacro('\acsa{}',              '\@acs{#1}');
DefMacro('\@acs{}',              '\acsfont{\AC@acs{#1}}\ifAC@starred\else\AC@logged{#1}\fi');

# Long form
DefMacro('\acl OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@acl');
DefMacro('\@acl{}',              '\acsfont{\AC@acl{#1}}\ifAC@starred\else\AC@logged{#1}\fi');

# Full form: Long (short)
DefMacro('\acf OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acfa');
DefMacro('\acfa{}',              '\@acf{#1}');
DefMacro('\@acf{}',
  '\ifAC@footnote\acsfont{\AC@acs{#1}}\footnote{\AC@placelabel{#1} \AC@acl{#1}}
  \else\acffont{\AC@placelabel{#1} \AC@acl{#1} \acfsfont{(\acsfont{\AC@acs{#1}})}}\fi
  \ifAC@starred\else\lx@AC@used{#1}\fi');

# Italicized long (short)

DefMacro('\acfi OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acfia');
DefMacro('\acfia{}',              '{\itshape\AC@acl{#1} }(\ifAC@starred\acs*{#1}\else\acs{#1}\fi)');

# Auto form
DefMacro('\ac OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@ac');
DefMacro('\@ac{}',
  '\lx@AC@if{#1}{\ifAC@starred\acs*{#1}\else\acs{#1}\fi}{\ifAC@starred\acf*{#1}\else\acf{#1}\fi}');

# Indefinite article form
DefMacro('\iac OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@iac');
DefMacro('\Iac OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@Iac');

DefMacro('\@iac{}', '\@iaci{#1} \ifAC@starred\ac*{#1}\else\ac{#1}\fi');
DefMacro('\@Iac{}', '\@firstupper{\@iaci{#1}} \ifAC@starred\ac*{#1}\else\ac{#1}\fi');
# \@firstupper
# \newcommand*{\@iaci}[1]{%
#    \ifcsname fn@#1@IL\endcsname
#      \ifAC@dua
#         \csname fn@#1@IL\endcsname%
#      \else
#         \expandafter\ifx\csname ac@#1\endcsname\AC@used%
#         \csname fn@#1@IS\endcsname%
#       \else
#         \csname fn@#1@IL\endcsname%
#       \fi
#      \fi
#    \else
#    a%
#    \fi

# Plural forms
DefMacro('\acsp OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acspa');
DefMacro('\acspa{}',              '\@acsp{#1}');
DefMacro('\@acsp{}',              '\acsfont{\AC@acsp{#1}}\ifAC@starred\else\AC@logged{#1}\fi');

DefMacro('\aclp OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@aclp');
DefMacro('\@aclp{}',              '\AC@aclp{#1}\ifAC@starred\else\AC@logged{#1}\fi');

DefMacro('\acfp OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acfpa');
DefMacro('\acfpa{}',              '\@acfp{#1}');
DefMacro('\@acfp{}',
  '\ifAC@footnote\acsfont{\AC@acsp{#1}}\footnote{\AC@placelabel{#1} \AC@aclp{#1}}
 \else\acffont{\AC@placelabel{#1} \AC@aclp{#1} \acfsfont{(\acsfont{\AC@acsp{#1}})}}\fi
  \ifAC@starred\else\AC@logged{#1}\fi');

DefMacro('\acp OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\@acp');
DefMacro('\@acp{}', '\lx@AC@if{#1}{\AC@acsp{#1}}{\AC@aclp{#1}}\ifAC@starred\else\AC@logged{#1}\fi');

DefMacro('\acsu OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\acsua');
DefMacro('\acsua{}',              '\ifAC@starred\acs*{#1}\else\acs{#1}\fi\acused{#1}');
DefMacro('\aclu OptionalMatch:*', '\ifx.#1.\AC@starredfalse\else\AC@starredtrue\fi\aclua');
DefMacro('\aclua{}',              '\ifAC@starred\acl*{#1}\else\acl{#1}\fi\acused{#1}');

#======================================================================
# Defining Acronyms
DefEnvironment('{acronym}[]',
  "<ltx:glossary lists='acronym' class='ltx_acronym'>"
    . "<ltx:glossarylist>"
    . "#body"
    . "</ltx:glossarylist>"
    . "</ltx:glossary>",
  beforeDigest => sub { Let('\acro', '\lx@acro@item');
    Let('\acrodef', '\lx@acro@item'); },
  afterDigest     => sub { noteBackmatterElement($_[1], 'ltx:glossary'); },
  beforeConstruct => sub { adjustBackmatterElement($_[0], $_[1]); });

DefMacro('\acroextra{}', '#1');

# \lx@acro@item{key}{short}{long}
DefMacro('\lx@acro@item{}[]{}',
  '\lx@acro@@item{#1}{\ifx.#2.#1\else#2\fi}{#3}');
DefMacro('\lx@acro@@item{}{}{}',
  '\lx@acro@@@item{#1}{#2}{#3}{{\let\acroextra\@gobble #2}}{{\let\acroextra\@gobble #3}}');
DefConstructor('\lx@acro@@@item{}{}{}{}{}',
  "<ltx:glossaryentry inlist='acronym' key='#1'>"
    . "<ltx:glossaryphrase role='label'>#2</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='short'>#4</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='long'>#5</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='definition'>#3</ltx:glossaryphrase>"
    . "</ltx:glossaryentry>");
Tag('ltx:glossaryentry', afterClose => sub { GenerateID(@_, ''); });

DefMacro('\acrodef{}[]{}',
  '\lx@acro@@def{#1}{\ifx.#2.#1\else#2\fi}{#3}');
DefMacro('\lx@acro@@def{}{}{}',
  '\lx@acro@@@def{#1}{#2}{#3}{{\let\acroextra\@gobble #2}}{{\let\acroextra\@gobble #3}}');
DefConstructor('\lx@acro@@@def{}{}{}{}{}',
  "<ltx:glossarydefinition inlist='acronym' key='#1'>"
    . "<ltx:glossaryphrase role='label'>#2</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='short'>#4</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='long'>#5</ltx:glossaryphrase>"
    . "<ltx:glossaryphrase role='definition'>#3</ltx:glossaryphrase>"
    . "</ltx:glossarydefinition>");

Tag('ltx:glossarydefinition', afterClose => sub { GenerateID(@_, ''); });
# Should these be allowed inside ltx:glossarylist, or float outside it?

Let('\newacro', '\acrodef');
Let('\acro',    '\acrodef');

# The following define additional forms of the acronym expansions.
# They should be recorded in the document & scanned in post-processing,
# but need not appear within the acronym glossary.
# Non-standard definite articles
DefMacro('\lx@acro@phrase{}{}{}', '{\let\acroextra\@gobble\lx@@acro@phrase{#1}{#2}{#3}}');
# Let this float up, since it can be used within a glossarylist, but shouldn't end up there.
DefConstructor('\lx@@acro@phrase{}{}{}',
  "^ <ltx:glossarydefinition inlist='acronym' key='#1'>"
    . "<ltx:glossaryphrase role='#2'>#3</ltx:glossaryphrase>"
    . "</ltx:glossarydefinition>");

DefMacro('\acrodefindefinite{}{}{}',
  '\lx@acro@phrase{#1}{short-indefinite}{#2}\lx@acro@phrase{#1}{long-indefinite}{#3}');

Let('\acroindefinite',    '\acrodefindefinite');
Let('\newacroindefinite', '\acrodefindefinite');

# Non-standard plural forms
DefMacro('\acrodefplural{}[]{}',
  '\lx@acro@phrase{#1}{short-plural}{\ifx.#2.#1\else#2\fi}\lx@acro@phrase{#1}{long-plural}{#3}');

Let('\acroplural',    '\acrodefplural');
Let('\newacroplural', '\acrodefplural');
#======================================================================
1;
