% \iffalse meta-comment
%
% Copyright (C) 2008-2014 by Ulrich M. Schwarz
% Copyright (C) 2019      by Frank Mittelbach
% Copyright (C) 2020-     by Yukai Chou
%
% This file may be distributed and/or modified under the conditions of
% the LaTeX Project Public License, version 1.3c.
% The license can be obtained from
% http://www.latex-project.org/lppl/lppl-1.3c.txt
%
% \fi
%
%\iffalse (hide this from DocInput)
%<*patch>
%\fi
%
% This package is maybe not very suitable for the end user. It redefines
% |\newtheorem| in a way that lets other packages (or the user) add code
% to the newly-defined theorems, in a reasonably cross-compatible (with 
% the kernel, \pkg{theorem} and \pkg{amsthm}) way.
%
% \textbf{Warning:} the new |\newtheorem| is a superset of the allowed 
% syntax. For example, you can give a star and both optional arguments, 
% even though you cannot have an unnumbered theorem that shares a counter
% and yet has a different reset-regimen. At some point, your command is
% re-assembled and passed on to the original |\newtheorem|. This might
% complain, or give you the usual ``Missing |\begin{document}|'' that
% marks too many arguments in the preamble.
%
% \DescribeMacro{\addtotheorem(pre/post)(head/foot)hook}
% A call to |\addtotheorempreheadhook|\oarg{kind}\marg{code} will
% insert the code to be executed whenever a kind theorem is opened, before
% the actual call takes place. (I.e., before the header ``Kind 1.3 (Foo)''
% is typeset.) There are also posthooks that are executed after this header,
% and the same for the end of the environment, even though nothing
% interesting ever happens there. These are useful to put
% |\begin{shaded}|\dots |\end{shaded}| around your theorems.
% Note that foothooks are executed LIFO (last addition first) and headhooks
% are executed FIFO (first addition first). There is a special kind called
% generic that is called for all theorems. This is the default if no kind
% is given.
%
% The added code may examine |\thmt@thmname| to get the title,
% |\thmt@envname| to get the environment's name, and |\thmt@optarg| to get
% the extra optional title, if any.
%
%\StopEventually{}
%    \begin{macrocode}
\RequirePackage{parseargs}

\newif\ifthmt@isstarred
\newif\ifthmt@hassibling
\newif\ifthmt@hasparent

\def\thmt@parsetheoremargs#1{%
  \parse{%
    {\parseOpt[]{\def\thmt@optarg{##1}}{%
      \let\thmt@shortoptarg\@empty
      \let\thmt@optarg\@empty}}%
    {%
      \def\thmt@local@preheadhook{}%
      \def\thmt@local@postheadhook{}%
      \def\thmt@local@prefoothook{}%
      \def\thmt@local@postfoothook{}%
      \thmt@local@preheadhook
      \csname thmt@#1@preheadhook\endcsname
      \thmt@generic@preheadhook
      % change following to \@xa-orgy at some point?
      % forex, might have keyvals involving commands.
      %\protected@edef\tmp@args{%
      %  \ifx\@empty\thmt@optarg\else [{\thmt@optarg}]\fi
      %}%
      \ifx\@empty\thmt@optarg
        \def\tmp@args{}%
      \else 
        \@xa\def\@xa\tmp@args\@xa{\@xa[\@xa{\thmt@optarg}]}%
      \fi
      \csname thmt@original@#1\@xa\endcsname\tmp@args
      %%moved down: \thmt@local@postheadhook
      %% (give postheadhooks a chance to re-set nameref data)
      \csname thmt@#1@postheadhook\endcsname
      \thmt@generic@postheadhook
      \thmt@local@postheadhook
%FMi 2019-07-31
%      \let\@parsecmd\@empty
      \let\@parsecmd\ignorespaces
%FMi ---      
    }%
  }%
}%

\let\thmt@original@newtheorem\newtheorem
\let\thmt@theoremdefiner\thmt@original@newtheorem

\def\newtheorem{%
  \thmt@isstarredfalse
  \thmt@hassiblingfalse
  \thmt@hasparentfalse
  \parse{%
    {\parseFlag*{\thmt@isstarredtrue}{}}%
    {\parseMand{\def\thmt@envname{##1}}}%
    {\parseOpt[]{\thmt@hassiblingtrue\def\thmt@sibling{##1}}{}}%
    {\parseMand{\def\thmt@thmname{##1}}}%
    {\parseOpt[]{\thmt@hasparenttrue\def\thmt@parent{##1}}{}}%
    {\let\@parsecmd\thmt@newtheoremiv}%
  }%
}

\newcommand\thmt@newtheoremiv{%
  \thmt@newtheorem@predefinition
  % whee, now reassemble the whole shebang.
  \protected@edef\thmt@args{%
    \@nx\thmt@theoremdefiner%
    \ifthmt@isstarred *\fi
    {\thmt@envname}%
    \ifthmt@hassibling [\thmt@sibling]\fi
    {\thmt@thmname}%
    \ifthmt@hasparent [\thmt@parent]\fi
  }
  \thmt@args
  \thmt@newtheorem@postdefinition
}

\newcommand\thmt@newtheorem@predefinition{}
\newcommand\thmt@newtheorem@postdefinition{%
  \let\thmt@theoremdefiner\thmt@original@newtheorem
}

\g@addto@macro\thmt@newtheorem@predefinition{%
  \@xa\thmt@providetheoremhooks\@xa{\thmt@envname}%
}
\g@addto@macro\thmt@newtheorem@postdefinition{%
  \@xa\thmt@addtheoremhook\@xa{\thmt@envname}%
  \ifthmt@isstarred\@namedef{the\thmt@envname}{}\fi
  \protected@edef\thmt@tmp{%
    \def\@nx\thmt@envname{\thmt@envname}%
    \def\@nx\thmt@thmname{\thmt@thmname}%
  }%
  \@xa\addtotheorempreheadhook\@xa[\@xa\thmt@envname\@xa]\@xa{%
    \thmt@tmp
  }%
}
\newcommand\thmt@providetheoremhooks[1]{%
  \@namedef{thmt@#1@preheadhook}{}%
  \@namedef{thmt@#1@postheadhook}{}%
  \@namedef{thmt@#1@prefoothook}{}%
  \@namedef{thmt@#1@postfoothook}{}%
  \def\thmt@local@preheadhook{}%
  \def\thmt@local@postheadhook{}%
  \def\thmt@local@prefoothook{}%
  \def\thmt@local@postfoothook{}%
}
\newcommand\thmt@addtheoremhook[1]{%
  % this adds two command calls to the newly-defined theorem.
  \@xa\let\csname thmt@original@#1\@xa\endcsname
          \csname#1\endcsname
  \@xa\renewcommand\csname #1\endcsname{%
    \thmt@parsetheoremargs{#1}%
  }%
  \@xa\let\csname thmt@original@end#1\@xa\endcsname\csname end#1\endcsname
  \@xa\def\csname end#1\endcsname{%
    % these need to be in opposite order of headhooks.
    \csname thmt@generic@prefoothook\endcsname
    \csname thmt@#1@prefoothook\endcsname
    \csname thmt@local@prefoothook\endcsname
    \csname thmt@original@end#1\endcsname
    \csname thmt@generic@postfoothook\endcsname
    \csname thmt@#1@postfoothook\endcsname
    \csname thmt@local@postfoothook\endcsname
  }%
}
\newcommand\thmt@generic@preheadhook{\refstepcounter{thmt@dummyctr}}
\newcommand\thmt@generic@postheadhook{}
\newcommand\thmt@generic@prefoothook{}
\newcommand\thmt@generic@postfoothook{}

\def\thmt@local@preheadhook{}
\def\thmt@local@postheadhook{}
\def\thmt@local@prefoothook{}
\def\thmt@local@postfoothook{}


\providecommand\g@prependto@macro[2]{%
  \begingroup
    \toks@\@xa{\@xa{#1}{#2}}%
    \def\tmp@a##1##2{##2##1}%
    \@xa\@xa\@xa\gdef\@xa\@xa\@xa#1\@xa\@xa\@xa{\@xa\tmp@a\the\toks@}%
  \endgroup
}

\newcommand\addtotheorempreheadhook[1][generic]{%
  \expandafter\g@addto@macro\csname thmt@#1@preheadhook\endcsname%
}
\newcommand\addtotheorempostheadhook[1][generic]{%
  \expandafter\g@addto@macro\csname thmt@#1@postheadhook\endcsname%
}

\newcommand\addtotheoremprefoothook[1][generic]{%
  \expandafter\g@prependto@macro\csname thmt@#1@prefoothook\endcsname%
}
\newcommand\addtotheorempostfoothook[1][generic]{%
  \expandafter\g@prependto@macro\csname thmt@#1@postfoothook\endcsname%
}

%    \end{macrocode}
% Since rev1.16, we add hooks to the proof environment as well, if it exists.
% If it doesn't exist at this point, we're probably using ntheorem as
% backend, where it goes through the regular theorem mechanism anyway.
%    \begin{macrocode}
\ifx\proof\endproof\else% yup, that's a quaint way of doing it :)
  % FIXME: this assumes proof has the syntax of theorems, which 
  % usually happens to be true (optarg overrides "Proof" string).
  % FIXME: refactor into thmt@addtheoremhook, but we really don't want to
  % call the generic-hook...
  \let\thmt@original@proof=\proof
  \renewcommand\proof{%
    \thmt@parseproofargs%
  }%
  \def\thmt@parseproofargs{%
    \parse{%
      {\parseOpt[]{\def\thmt@optarg{##1}}{\let\thmt@optarg\@empty}}%
      {%
        \thmt@proof@preheadhook
        %\thmt@generic@preheadhook
        \protected@edef\tmp@args{%
          \ifx\@empty\thmt@optarg\else [\thmt@optarg]\fi
        }%
        \csname thmt@original@proof\@xa\endcsname\tmp@args
        \thmt@proof@postheadhook
        %\thmt@generic@postheadhook
        \let\@parsecmd\@empty
      }%
    }%
  }%
  
  \let\thmt@original@endproof=\endproof
  \def\endproof{%
    % these need to be in opposite order of headhooks.
    %\csname thmtgeneric@prefoothook\endcsname
    \thmt@proof@prefoothook
    \thmt@original@endproof
    %\csname thmt@generic@postfoothook\endcsname
    \thmt@proof@postfoothook
  }%
  \@namedef{thmt@proof@preheadhook}{}%
  \@namedef{thmt@proof@postheadhook}{}%
  \@namedef{thmt@proof@prefoothook}{}%
  \@namedef{thmt@proof@postfoothook}{}%
\fi
%    \end{macrocode}
%\iffalse
%</patch>
%\fi
