% memoir-tcolorbox.sty
% Forces ALL footnotes to use main footnote numbering and paragraph formatting
% Complete rewrite based on footnotehyper but adapted for memoir paragraph footnotes

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{memoir-tcolorbox}[2024/01/01 v3.0 Memoir paragraph footnote fix with full hyperref]

% Use etoolbox for robust patching
\RequirePackage{etoolbox}

% Debug mode with extensive logging
\newif\ifMFS@debug
\MFS@debugfalse % Disable debug for production
\def\MFS@debug#1{\ifMFS@debug\typeout{[MFS] #1}\fi}
\def\MFS@debugmark#1{\ifMFS@debug\typeout{[MFS-MARK] #1}\fi}
\def\MFS@debugtext#1{\ifMFS@debug\typeout{[MFS-TEXT] #1}\fi}
\def\MFS@debughref#1{\ifMFS@debug\typeout{[MFS-HREF] #1}\fi}

% Only works with memoir
\@ifclassloaded{memoir}{}{%
  \PackageError{memoir-tcolorbox}{This package requires the memoir class}{}%
}

% Storage for saved footnotes
\newbox\MFS@notes
\newdimen\MFS@width
\newdimen\MFS@notes@height % Track accumulated footnote height for tcolorbox
\newif\ifMFS@savingnotes
\newif\ifMFS@globalmode % New flag for global save mode

% Track column width
\let\MFS@colwidth\columnwidth

% Storage for footnote counter state
\newcount\MFS@footnote@count
\newcount\MFS@mpfootnote@count

% Track hyperref state
\newif\ifMFS@hyperref
\newif\ifMFS@hyperfootnotes

% Flag to control footnote space reservation
\newif\ifMFS@reserve@space
\MFS@reserve@spacefalse % default: do not reserve space

\AtBeginDocument{%
    \MFS@debug{=== MFS Setup Starting ===}%
    
    % Save original commands BEFORE any modifications
    \let\MFS@latex@footnote\footnote
    \let\MFS@latex@footnotetext\footnotetext
    \let\MFS@H@@footnotetext\@footnotetext
    \let\MFS@H@@mpfootnotetext\@mpfootnotetext
    
    % Save memoir's paragraph footnote command
    \let\MFS@memoir@@parafootnotetext\@parafootnotetext
    
    % Check for hyperref
    \@ifpackageloaded{hyperref}{%
        \MFS@hyperreftrue
        \MFS@debug{Hyperref detected}%
        \ifHy@hyperfootnotes
            \MFS@hyperfootnotestrue
            \MFS@debug{Hyperref footnotes enabled}%
            % Save hyperref's versions if they exist
            \@ifundefined{H@@footnotetext}{}{%
                \let\MFS@H@@footnotetext\H@@footnotetext
                \let\MFS@H@@mpfootnotetext\H@@mpfootnotetext
            }%
        \else
            \MFS@debug{Hyperref footnotes disabled}%
        \fi
    }{%
        \MFS@debug{No hyperref}%
    }%
    
    % CRITICAL: Enable global save mode to process ALL footnotes
    % This ensures hyperref links work for all footnotes
    \MFS@globalmodetrue
    \MFS@begin@global@mode
    
    \MFS@debug{=== MFS Setup Complete ===}%
}

% ============================================================================
% Global mode - process ALL footnotes through save/restore
% ============================================================================

\def\MFS@begin@global@mode{%
    \MFS@debug{Enabling global footnote processing mode}%
    % Replace the main footnote commands
    \let\footnote\MFS@footnote
    \let\footnotetext\MFS@footnotetext
    % Replace low-level commands
    \let\@footnotetext\MFS@hyper@fntext
    \let\@mpfootnotetext\MFS@hyper@fntext
}

% ============================================================================
% Core save/restore mechanism (based on footnotehyper)
% ============================================================================

% Main wrapper to check amsmath measuring
\def\MFS@fntext#1{%
    \ifx\ifmeasuring@\@undefined
        \expandafter\@secondoftwo
    \else
        \expandafter\@firstofone
    \fi
    {\ifmeasuring@\expandafter\@gobbletwo\fi}#1%
}

% Main processing function with hyperref
\def\MFS@hyper@fntext{\MFS@fntext\MFS@hyper@fntext@impl}
\def\MFS@nohyp@fntext{\MFS@fntext\MFS@nohyp@fntext@impl}

% Store with hyperref support - format as memoir paragraph footnote
\long\def\MFS@hyper@fntext@impl#1{%
    \MFS@debughref{Processing footnote \@thefnmark, href=\Hy@footnote@currentHref}%
    % Directly insert formatted paragraph footnote
    \insert\footinsv@r{%
        \def\baselinestretch{\m@m@footnote@spacing}%
        \reset@font\foottextfont
        \@preamfntext
        \protected@edef\@currentlabel{%
            \csname p@footnote\endcsname\@thefnmark}%
        \setbox0=\vbox{\hsize=\maxdimen
            \color@begingroup
            \noindent\@parafootfmt{%
                \ifMFS@hyperfootnotes
                    \ifHy@nesting
                        \expandafter\ltx@firstoftwo
                    \else
                        \expandafter\ltx@secondoftwo
                    \fi
                    {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}%
                    {\Hy@raisedlink{%
                        \expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{\relax}%
                    }%
                    \let\@currentHref\Hy@footnote@currentHref
                    \let\@currentlabelname\@empty
                    #1}%
                \else
                    #1%
                \fi
            }%
            \color@endgroup
        }%
        \m@mungebox
    }%
    \m@mmf@prepare
}

% Store without hyperref - format as memoir paragraph footnote
\long\def\MFS@nohyp@fntext@impl#1{%
    \MFS@debugtext{Processing footnote without hyperref}%
    \insert\footinsv@r{%
        \def\baselinestretch{\m@m@footnote@spacing}%
        \reset@font\foottextfont
        \@preamfntext
        \protected@edef\@currentlabel{%
            \csname p@footnote\endcsname\@thefnmark}%
        \setbox0=\vbox{\hsize=\maxdimen
            \color@begingroup
            \noindent\@parafootfmt{#1}%
            \color@endgroup
        }%
        \m@mungebox
    }%
    \m@mmf@prepare
}

% Main footnote command that works everywhere
\def\MFS@footnote{%
    \@ifnextchar[%
        {\MFS@footnote@opt}%
        {\MFS@footnote@noopt}%
}

\def\MFS@footnote@opt[#1]{%
    \MFS@debugmark{footnote[#1] called, savingnotes=\ifMFS@savingnotes true\else false\fi}%
    \ifMFS@savingnotes
        % In save mode: store for later
        \footnotemark[#1]%
        \MFS@store@footnote@opt[#1]%
    \else
        % Normal mode but still process through our system
        \MFS@latex@footnote[#1]%
    \fi
}

\def\MFS@footnote@noopt#1{%
    \MFS@debugmark{footnote{...} called, savingnotes=\ifMFS@savingnotes true\else false\fi}%
    \ifMFS@savingnotes
        % In save mode: store for later
        \footnotemark
        \MFS@store@footnote@noopt{#1}%
    \else
        % Normal mode but still process through our system
        \MFS@latex@footnote{#1}%
    \fi
}

% Main footnotetext command
\def\MFS@footnotetext{%
    \@ifnextchar[%
        {\MFS@footnotetext@opt}%
        {\MFS@footnotetext@noopt}%
}

\def\MFS@footnotetext@opt[#1]{%
    \MFS@debugtext{footnotetext[#1] called}%
    \ifMFS@savingnotes
        \MFS@store@footnote@opt[#1]%
    \else
        \MFS@latex@footnotetext[#1]%
    \fi
}

\def\MFS@footnotetext@noopt#1{%
    \MFS@debugtext{footnotetext{...} called}%
    \ifMFS@savingnotes
        \MFS@store@footnote@noopt{#1}%
    \else
        \MFS@latex@footnotetext{#1}%
    \fi
}

% Store footnote for later (save mode)
\def\MFS@store@footnote@opt[#1]#2{%
    \begingroup
    \csname c@\@mpfn\endcsname #1\relax
    \unrestored@protected@xdef\@thefnmark{\thempfn}%
    \endgroup
    \MFS@store@footnote@impl{#2}%
}

\def\MFS@store@footnote@noopt#1{%
    \MFS@store@footnote@impl{#1}%
}

\long\def\MFS@store@footnote@impl#1{%
    \MFS@debugtext{Storing footnote \@thefnmark for later}%
    % Build the formatted footnote exactly as memoir would
    \global\setbox\MFS@notes\vbox{%
        \unvbox\MFS@notes
        % Start a new footnote
        \setbox0=\vbox{\hsize=\maxdimen
            \color@begingroup
            \noindent\@parafootfmt{%
                \ifMFS@hyperfootnotes
                    \ifHy@nesting
                        \expandafter\ltx@firstoftwo
                    \else
                        \expandafter\ltx@secondoftwo
                    \fi
                    {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}%
                    {\Hy@raisedlink{%
                        \expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{\relax}%
                    }%
                    \let\@currentHref\Hy@footnote@currentHref
                    \let\@currentlabelname\@empty
                    #1}%
                \else
                    #1%
                \fi
            }%
            \color@endgroup
        }%
        % Convert to hbox for paragraph format
        \setbox0=\hbox{\m@munvxh0}%
        \dp0=\z@
        \ht0=\footfudgefactor\wd0
        \box0
        \penalty0
    }%
    % Update accumulated height for tcolorbox break calculation
    \global\MFS@notes@height=\ht\MFS@notes
    \MFS@debug{Accumulated footnote height: \the\MFS@notes@height}%
}

% Save notes mode (for tcolorbox)
\def\MFS@savenotes{%
    \MFS@debug{>>> SAVENOTES called}%
    \ifMFS@savingnotes
        \MFS@debug{Already in save mode}%
    \else
        \global\MFS@savingnotestrue

        % Save counter values
        \MFS@footnote@count=\c@footnote
        \MFS@mpfootnote@count=\c@mpfootnote

        % Initialize storage
        \MFS@width\columnwidth
        \let\MFS@colwidth\MFS@width
        \global\setbox\MFS@notes\box\voidb@x
        \global\MFS@notes@height=0pt % Reset accumulated footnote height

        % Save minipage state
        \let\MFS@thempfn\thempfn
        \let\MFS@mpfn\@mpfn

        % Force main footnote counter
        \def\@mpfn{footnote}%
        \let\thempfn\thefootnote

        \MFS@debug{Save mode activated}%
    \fi
}

% Restore notes mode (for tcolorbox)
\def\MFS@restorenotes{%
    \MFS@debug{<<< RESTORENOTES called}%
    \ifMFS@savingnotes
        \global\MFS@savingnotesfalse

        % Restore minipage state
        \let\thempfn\MFS@thempfn
        \let\@mpfn\MFS@mpfn

        % Restore counters
        \c@footnote=\MFS@footnote@count
        \c@mpfootnote=\MFS@mpfootnote@count

        \MFS@debug{Save mode deactivated}%
    \fi

    % Output saved notes
    \ifvoid\MFS@notes
        \MFS@debug{No notes to output}%
    \else
        \MFS@debug{Outputting saved notes to footinsv@r}%
        \insert\footinsv@r{\unvbox\MFS@notes}%
    \fi
    % Reset accumulated height
    \global\MFS@notes@height=0pt
}

% ============================================================================
% Hook into tcolorbox
% ============================================================================

\AtBeginDocument{%
    \@ifpackageloaded{tcolorbox}{%
        \MFS@debug{Configuring tcolorbox integration}%
        \tcbset{%
            before upper={\MFS@savenotes},
            after={\MFS@restorenotes},
            reserve footnote space/.is if=MFS@reserve@space,
        }%
        % Patch tcb@comp@h@page to account for accumulated footnote height
        % This ensures breakable boxes reserve space for footnotes
        \@ifundefined{tcb@comp@h@page}{}{%
            \MFS@debug{Patching tcb@comp@h@page for footnote awareness}%
            \let\MFS@orig@tcb@comp@h@page\tcb@comp@h@page
            \def\tcb@comp@h@page{%
                \MFS@orig@tcb@comp@h@page
                % Only reserve space if flag is enabled
                \ifMFS@reserve@space
                    \ifdim\MFS@notes@height>0pt\relax
                        \tcbdimto\tcb@h@page{\tcb@h@page-\MFS@notes@height-\skip\footinsv@r}%
                        \MFS@debug{Reduced tcb@h@page by \the\MFS@notes@height\space for footnotes}%
                    \fi
                \fi
            }%
        }%
        \MFS@debug{tcolorbox configured}%
    }{%
        \MFS@debug{tcolorbox not loaded}%
    }%
}

\endinput
