% Copyright 2026 Open-Guji (https://github.com/open-guji)
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
%     http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
% luatex-cn-core-sidenote.sty
% SideNode (侧批) support for vertical typesetting
% This is a subpackage of luatex_cn
%
\RequirePackage{core/luatex-cn-core-base}
\RequirePackage{expl3}
\RequirePackage{xparse}
\ProvidesExplPackage {core/luatex-cn-core-sidenote} {2026/02/18} {0.3.0} {SideNode Support for Vertical Typesetting}

% Define keys for SideNode
\tl_new:N \l__luatexcn_sidenote_yshift_tl
\tl_new:N \l__luatexcn_sidenote_grid_height_tl
\tl_new:N \l__luatexcn_sidenote_font_size_tl
\tl_new:N \l__luatexcn_sidenote_color_tl
\tl_new:N \l__luatexcn_sidenote_padding_top_tl
\tl_new:N \l__luatexcn_sidenote_padding_bottom_tl

\keys_define:nn { luatexcn / sidenode }
  {
    yshift .tl_set:N = \l__luatexcn_sidenote_yshift_tl,
    yshift .initial:n = 0pt,
    grid-height .tl_set:N = \l__luatexcn_sidenote_grid_height_tl,
    font-size .tl_set:N = \l__luatexcn_sidenote_font_size_tl,
    font-size .initial:n = 10pt,
    color .tl_set:N = \l__luatexcn_sidenote_color_tl,
    color .initial:n = red,
    border-padding-top .tl_set:N = \l__luatexcn_sidenote_padding_top_tl,
    border-padding-top .initial:n = 0pt,
    border-padding-bottom .tl_set:N = \l__luatexcn_sidenote_padding_bottom_tl,
    border-padding-bottom .initial:n = 0pt,
  }

\NewDocumentCommand{\sidenodeSetup}{ m }
  {
    \keys_set:nn { luatexcn / sidenode } { #1 }
  }

\NewDocumentCommand{\SideNode}{ O{} +m }{%
  \group_begin:
    % Process optional argument: handle positional parameter (plain number → em)
    \tl_if_empty:nTF { #1 }
      {
        % Empty argument: no special processing needed
      }
      {
        % Check if it's a plain number by attempting regex match
        \regex_match:nnTF { ^\d+(?:\.\d+)?$ } { #1 }
          {
            % Plain number: convert to em
            \tl_set:Nn \l_tmpa_tl { yshift = #1 em }
            \keys_set:nn { luatexcn / sidenode } { yshift = #1 em }
          }
          {
            % Not a plain number: check if it has '='
            \regex_match:nnTF { = } { #1 }
              {
                % Contains '=': use as-is (named parameter like color=red)
                \keys_set:nn { luatexcn / sidenode } { #1 }
              }
              {
                % No '=': treat as positional yshift with units
                \keys_set:nn { luatexcn / sidenode } { yshift = #1 }
              }
          }
      }
    % If #1 was empty, no keys to set (use defaults)
    % Use explicit font size
    \tl_if_empty:NTF \l__luatexcn_sidenote_font_size_tl
      { \dim_set:Nn \l_tmpa_dim { \f@size pt } }
      { \dim_set:Nn \l_tmpa_dim { \__luatexcn_to_dimen:n { \l__luatexcn_sidenote_font_size_tl } } }
    \fontsize{\l_tmpa_dim}{\l_tmpa_dim}\selectfont
    % DO NOT use \textcolor here - it creates pdf_colorstack nodes that cause
    % color leakage when sidenotes span across page boundaries.
    % Color is handled entirely in the Lua render layer via PDF literals.
    \hbox_set:Nn \l_tmpa_box {#2}%

    % Prepare metadata
    \dim_set:Nn \l_tmpb_dim { \__luatexcn_to_dimen:n { \l__luatexcn_sidenote_grid_height_tl } }
    % If grid-height not set, default to font size (tight packing)
    \dim_compare:nF { \l_tmpb_dim > 0pt } { \dim_set_eq:NN \l_tmpb_dim \l_tmpa_dim }

    % Pass style attributes to Lua (style registration handled in Lua layer)
    \lua_now:e { vertical_sidenote.register_sidenote(\int_value:w \l_tmpa_box, {
      yshift = vertical_constants.to_dimen([=[\luaescapestring{\tl_use:N \l__luatexcn_sidenote_yshift_tl}]=]) ~ or ~ 0,
      grid_height = \int_value:w \l_tmpb_dim,
      padding_top = vertical_constants.to_dimen([=[\luaescapestring{\tl_use:N \l__luatexcn_sidenote_padding_top_tl}]=]) ~ or ~ 0,
      padding_bottom = vertical_constants.to_dimen([=[\luaescapestring{\tl_use:N \l__luatexcn_sidenote_padding_bottom_tl}]=]) ~ or ~ 0,
      font_color = [=[\luaescapestring{\tl_use:N \l__luatexcn_sidenote_color_tl}]=],
      font_size = [=[\luaescapestring{\dim_use:N \l_tmpa_dim}]=]
    })}%
  \group_end:
}

\ExplSyntaxOff%

% ============================================================
% Chinese aliases / 中文别名
% ============================================================
% Simplified Chinese / 简体
\NewCommandCopy{\侧批}{\SideNode}
\NewCommandCopy{\CePi}{\SideNode}
\NewCommandCopy{\侧批设置}{\sidenodeSetup}
% Traditional Chinese / 繁体
\NewCommandCopy{\側批}{\SideNode}
\NewCommandCopy{\側批設置}{\sidenodeSetup}

% ============================================================
% Chinese key aliases / 中文 Key 别名
% ============================================================
\ExplSyntaxOn
\keys_define:nn { luatexcn / sidenode }
  {
    % 简体
    纵移 .tl_set:N = \l__luatexcn_sidenote_yshift_tl,
    格高 .tl_set:N = \l__luatexcn_sidenote_grid_height_tl,
    字号 .tl_set:N = \l__luatexcn_sidenote_font_size_tl,
    颜色 .tl_set:N = \l__luatexcn_sidenote_color_tl,
    边框上填充 .tl_set:N = \l__luatexcn_sidenote_padding_top_tl,
    边框下填充 .tl_set:N = \l__luatexcn_sidenote_padding_bottom_tl,
    % 繁体（与简体不同形的）
    縱移 .tl_set:N = \l__luatexcn_sidenote_yshift_tl,
    字號 .tl_set:N = \l__luatexcn_sidenote_font_size_tl,
    顏色 .tl_set:N = \l__luatexcn_sidenote_color_tl,
  }
\ExplSyntaxOff

\endinput%
