%
% Copyright (c) 2021-2025 Zeping Lee
% Released under the MIT License.
% Repository: https://github.com/zepinglee/citeproc-lua
%

% ## Compatibilities with other packages

% ### `babel`

% This should be disabled.
\hook_gput_code:nnn { package / babel / after } { . }
  {
    \RenewDocumentCommand \nocite { m }
      {
        % \@safe@activestrue\org@nocite{#1}\@safe@activesfalse
        \@safe@activestrue
        \__csl_no_cite:n {#1}
        \@safe@activesfalse
      }
    \cs_set_eq:NN \bbl@cite@choice \relax
    \cs_set_eq:NN \@lbibitem \__csl_lbibitem_plain:nn
    \cs_set_eq:NN \@bibitem \__csl_bibitem_plain:n
  }


% ### `backref`

\hook_gput_code:nnn { package / backref / after } { . }
  {
    \cs_set:Npn \__csl_add_back_ref_info:
      { \seq_map_inline:Nn \l__csl_cite_keys_seq { \Hy@backout {##1} } }
  }


% ### `beamer`

% `beamer` passes `implicit=false` to `hyperref` to skip its patch to LaTeX2e
% internal bibliographic commands. Instead `beamer` refines those commands
% in its own way.

\cs_new:Npn \__csl_beamer_cite_item:nn #1#2
  { \hyperlink { beamerbib #1 } { #2 } }

\cs_new:Npn \__csl_beamer_lbibitem:nn [#1]#2
  {
    \exp_after:wN \item \beamer@bibstore [ \@biblabel {#1} \hfill ]
    \cs_if_exist:cF { beamerbib@ #2 @ \int_use:N \c@framenumber }
      {
        \cs_gset:cpn { beamerbib@ #2 @ \int_use:N \c@framenumber } { \relax }
        \hypertarget { beamerbib #2 } { }
      }
    \hbox { }
    \ignorespaces
  }

\cs_new:Npn \__csl_beamer_bibitem:n #1
  {
    \exp_after:wN \item \beamer@bibstore
    \cs_if_exist:cF { beamerbib@ #1 @ \int_use:N \c@framenumber }
      {
        \cs_gset:cpn { beamerbib@ #1 @ \int_use:N \c@framenumber } { \relax }
        \hypertarget { beamerbib #1 } { }
      }
  }

\hook_gput_code:nnn { class / beamer / after } { . }
  {
    \cs_gset_eq:NN \@lbibitem \__csl_beamer_lbibitem:nn
    \cs_gset_eq:NN \@bibitem \__csl_beamer_bibitem:n
    \cs_gset_eq:NN \cslcite \__csl_beamer_cite_item:nn
  }


% ### `biblatex`
% The following doesn't really make `csl` compatible with `biblatex`.
% It just provides commands to make it accepting `biblatex`'s database.

\ProvideDocumentCommand { \hyphen } { }
  {
    \nobreak - \nobreak
    \hskip \z@skip
  }


% ### `csquotes`

\hook_gput_code:nnn { package / csquotes / after } { . }
  {
    \BlockquoteDisable
      {
        \cs_set_eq:NN \__csl_process_citation_info: \relax
        \cs_set_eq:NN \__csl_make_citation: \relax
      }
  }


% ### `hyperref`

% The hyperref package also patches \bibcite but it cannot provide hyperlinks
% when used with csl.
\bool_new:N \l__csl_hyperref_loaded_bool
\hook_gput_code:nnn { package / hyperref / after } { . }
  {
    \bool_set_true:N \l__csl_hyperref_loaded_bool
    % Pakcage "hyperref" redefines \@lbibitem and \bibitem and we need to
    % recover them.
    % In non-implicit mode (e.g., loaded by `beamer`), hyperref stops early
    % (`\MaybeStopEarly`) and it doesn't redefine the cite internal commands.
    \cs_if_exist:NT \@extra@b@citeb
      {
        \cs_gset_eq:NN \cslcite \__csl_hyperref_cite_item:nn
        \cs_gset_eq:NN \@lbibitem \__csl_lbibitem:
        \cs_gset_eq:NN \@bibitem \__csl_bibitem:
        \cs_gset_eq:NN \__csl_lbibitem_plain:nn \__csl_hyperref_lbibitem:nn
        \cs_gset_eq:NN \__csl_bibitem_plain:n \__csl_hyperref_bibitem:n
        \cs_gset_eq:NN \__csl_process_entry_ids:n \__csl_hyperref_process_entry_ids:n
        \cs_gset_eq:NN \__csl_process_excluded_ids:n \__csl_hyperref_process_excluded_ids:n
        \cs_gset_eq:NN \__csl_read_entry_ids: \__csl_hyperref_read_entry_ids:
      }
  }

\clist_new:N \l__csl_ref_section_entry_ids_clist
\clist_new:N \l__csl_ref_section_excluded_ids_clist

\cs_new:Npn \__csl_hyperref_cite_item:nn #1#2
  {
    % \clist_show:N \l__csl_ref_section_excluded_ids_clist
    % \clist_show:N \l__csl_ref_section_entry_ids_clist
    \clist_if_in:NnTF \l__csl_ref_section_excluded_ids_clist {#1}
      {
        \clist_if_in:NnTF \l__csl_ref_section_entry_ids_clist {#1}
          {
            \hyper@@link [ cite ] { }
              { cite \int_use:N \g__csl_ref_section_index_int . #1 \@extra@b@citeb } {#2}
          }
          {#2}
      }
      {
        \hyper@@link [ cite ] { }
          { cite \int_use:N \g__csl_ref_section_index_int . #1 \@extra@b@citeb } {#2}
      }
  }

\cs_new:Npn \__csl_hyperref_lbibitem:nn [#1]#2
  {
    \@skiphyperreftrue
    \H@item
      [
        \ifx \Hy@raisedlink \@empty
          \hyper@anchorstart
            { cite \int_use:N \g__csl_ref_section_index_int . #2 \@extra@b@citeb }
          \@BIBLABEL {#1}
          \hyper@anchorend
        \else
          \Hy@raisedlink
            {
              \hyper@anchorstart
                { cite \int_use:N \g__csl_ref_section_index_int . #2 \@extra@b@citeb }
              \hyper@anchorend
            }
          \@BIBLABEL {#1}
        \fi
        \hfill
      ]
    \@skiphyperreffalse
    \ignorespaces
  }

\cs_new:Npn \__csl_hyperref_bibitem:n #1
  {
    \@skiphyperreftrue \H@item \@skiphyperreffalse
    \Hy@raisedlink
      {
        \hyper@anchorstart
          { cite \int_use:N \g__csl_ref_section_index_int . #1 \@extra@b@citeb }
        \relax
        \hyper@anchorend
      }
    \ignorespaces
  }

\prop_new:N \g__csl_entry_ids_prop
\prop_new:N \g__csl_excluded_ids_prop

\cs_new:Npn \__csl_hyperref_process_entry_ids:n #1
  {
    \sys_if_engine_luatex:TF
      {
        \__csl_if_preamble:TF
          {
            % From `\csl@aux@options` commands in the `.aux` file
            \exp_args:NNV \__csl_append_entry_ids:Nnn \g__csl_entry_ids_prop
              \l__csl_ref_section_index_tl {#1}
          }
          {
            % From `\csloptions` commands via `\printbibliography`
            \__csl_write_aux_options:n { entry-ids = {#1} }
          }
      }
      {
        % Read by `\csloptions` commands from the `.bbl` file
        \exp_args:NNV \__csl_append_entry_ids:Nnn \g__csl_entry_ids_prop
          \l__csl_ref_section_index_tl {#1}
      }
  }

\cs_new:Npn \__csl_hyperref_process_excluded_ids:n #1
  {
    \sys_if_engine_luatex:TF
      {
        \__csl_if_preamble:TF
          {
            % From `\csl@aux@options` commands in the `.aux` file
            \exp_args:NNV \__csl_append_entry_ids:Nnn \g__csl_excluded_ids_prop
              \l__csl_ref_section_index_tl {#1}
          }
          {
            % From `\csloptions` commands via `\printbibliography`
            \__csl_write_aux_options:n { excluded-ids = {#1} }
          }
      }
      {
        % Read by `\csloptions` commands from the `.bbl` file
        \exp_args:NNV \__csl_append_entry_ids:Nnn \g__csl_excluded_ids_prop
          \l__csl_ref_section_index_tl {#1}
      }
  }

\cs_new:Npn \__csl_append_entry_ids:Nnn #1#2#3
  {
    \clist_clear:N \l_tmpa_clist
    \prop_get:NnNT #1 {#2} \l_tmpa_tl
      { \clist_set:NV \l_tmpa_clist \l_tmpa_tl }
    \clist_map_inline:nn {#3}
      {
        \clist_if_in:NnF \l_tmpa_clist {##1}
          { \clist_put_right:Nn \l_tmpa_clist {##1} }
      }
    \prop_gput:Nne #1 {#2}
      { \clist_use:Nn \l_tmpa_clist { , } }
  }

\cs_new:Npn \__csl_hyperref_read_entry_ids:
  {
    \prop_get:NeNT \g__csl_entry_ids_prop
      { \int_use:N \g__csl_ref_section_index_int } \l_tmpa_tl
      { \clist_set:NV \l__csl_ref_section_entry_ids_clist \l_tmpa_tl }
    \prop_get:NeNT \g__csl_excluded_ids_prop
      { \int_use:N \g__csl_ref_section_index_int } \l_tmpa_tl
      { \clist_set:NV \l__csl_ref_section_excluded_ids_clist \l_tmpa_tl }
  }


% ### `perpage`

\hook_gput_code:nnn { package / perpage / after } { . }
  {
    \hook_gput_code:nnn { begindocument } { . }
      {
        \cs_if_exist:cT { c@pchk@footnote }
          {
            \cs_set:Npn \__csl_make_chapter_property:
              {
                \prop_put:Nne \l__csl_citation_properties_prop { chapterIndex }
                  { \int_use:N \c@page }
              }
          }
      }
  }
