% 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-base.sty
% Foundational attributes and helpers for vertical typesetting
%
\RequirePackage{expl3}
\RequirePackage{luatexbase}
\RequirePackage{enumitem}

\ProvidesExplPackage {core/luatex-cn-core-base} {2026/10/29} {0.4.3} {Core base for luatex-cn}

% ============================================================================
% Attributes
% ============================================================================
\newluatexattribute\cnverticalindent
\newluatexattribute\cnverticalrightindent
\newluatexattribute\cnverticaltextboxwidth
\newluatexattribute\cnverticaltextboxheight
\newluatexattribute\cnverticaltextboxdistribute
\newluatexattribute\cnverticaljiazhu
\newluatexattribute\cnverticaljiazhusub
\newluatexattribute\cnverticaljiazhumode
\newluatexattribute\cnverticalblockid
\newluatexattribute\cnverticalfirstindent
\newluatexattribute\cnverticalstyle
\newluatexattribute\cnverticalcolumn
\newluatexattribute\cnverticalcolumnalign
\newluatexattribute\cnverticallinemark

\lua_now:e {
  luatex_cn_debug.register_module("vertical", { color = "yellow" })
}

% Clear cache and Load Modules
\lua_now:e {
  package.loaded["core.luatex-cn-constants"]~=~nil;
  package.loaded["util.luatex-cn-utils"]~=~nil;
  package.loaded["util.luatex-cn-text-utils"]~=~nil;
  package.loaded["core.luatex-cn-core-flatten-nodes"]~=~nil;
  package.loaded["core.luatex-cn-layout-grid"]~=~nil;
  package.loaded["core.luatex-cn-core-render-page"]~=~nil;
  package.loaded["core.luatex-cn-render-position"]~=~nil;
  package.loaded["core.luatex-cn-core-main"]~=~nil;
  package.loaded["core.luatex-cn-core-textbox"]~=~nil;
  package.loaded["core.luatex-cn-core-textflow"]~=~nil;
  package.loaded["core.luatex-cn-core-sidenote"]~=~nil;
  package.loaded["core.luatex-cn-core-column"]~=~nil;
  package.loaded["banxin.luatex-cn-banxin-main"]~=~nil;
  package.loaded["core.luatex-cn-hooks"]~=~nil;

  vertical_constants~=~require('core.luatex-cn-constants');
  vertical_utils~=~require('util.luatex-cn-utils');
  vertical_text_utils~=~require('util.luatex-cn-text-utils');
  vertical_hooks~=~require('core.luatex-cn-hooks');
  vertical_flatten~=~require('core.luatex-cn-core-flatten-nodes');
  vertical_layout~=~require('core.luatex-cn-layout-grid');
  vertical_text_position~=~require('core.luatex-cn-render-position');
  vertical_render~=~require('core.luatex-cn-core-render-page');
  vertical_textbox~=~require('core.luatex-cn-core-textbox');
  vertical_textflow~=~require('core.luatex-cn-core-textflow');
  vertical_sidenote~=~require('core.luatex-cn-core-sidenote');
  vertical~=~require('core.luatex-cn-core-main')
}

% ============================================================================
% Global Style Defaults
% ============================================================================
% Set itemize default style: empty label + compact spacing (classical style)
\setlist[itemize]{label={}, nosep}

% ============================================================================
% Common Helpers
% ============================================================================

% ----------------------------------------------------------------------------
% Unknown key forwarding (未知 key 转发)
% ----------------------------------------------------------------------------
% Most keyspaces (textflow / column / pizhu / meipi / sidenote / textbox /
% yinzhang / banxin ...) forward keys they do not define to the shared
% "settings" and "style" keyspaces.  Previously each of them silently dropped
% keys that no keyspace knew, so a typo or a wrong alias (e.g. issue #163's
% \jiazhuSetup{color=red}) failed with no diagnostic at all.  These helpers
% centralise that chain and warn on the dead end.

\msg_new:nnnn { luatex-cn } { unknown-key }
  { 未知选项~'#1'~已被忽略~(unknown~option~'#1'~ignored). }
  {
    该选项不属于任何已知的~luatex-cn~选项空间，因此没有任何效果。\\
    请检查拼写，或参阅手册中该命令支持的选项列表。\\
    This~option~is~not~known~to~any~luatex-cn~keyspace~and~had~no~effect.
  }

% #1 = key value.  Uses \l_keys_key_str for the key name.
% Chain: current keyspace (already missed) -> settings -> style -> warn.
\cs_new_protected:Npn \__luatexcn_keys_forward_unknown:n #1
  {
    \exp_args:Nnx \keys_if_exist:nnTF { luatexcn / settings } { \l_keys_key_str }
      { \keys_set:nx { luatexcn / settings } { \l_keys_key_str = { \exp_not:n {#1} } } }
      {
        \exp_args:Nnx \keys_if_exist:nnTF { luatexcn / style } { \l_keys_key_str }
          { \keys_set:nx { luatexcn / style } { \l_keys_key_str = { \exp_not:n {#1} } } }
          { \msg_warning:nnx { luatex-cn } { unknown-key } { \l_keys_key_str } }
      }
  }

% Variant for the "style" keyspace itself: forwarding to style would recurse
% back into this very handler, so it only tries settings before warning.
\cs_new_protected:Npn \__luatexcn_keys_forward_unknown_settings:n #1
  {
    \exp_args:Nnx \keys_if_exist:nnTF { luatexcn / settings } { \l_keys_key_str }
      { \keys_set:nx { luatexcn / settings } { \l_keys_key_str = { \exp_not:n {#1} } } }
      { \msg_warning:nnx { luatex-cn } { unknown-key } { \l_keys_key_str } }
  }

% Helper for unified dimension parsing (calls Lua)
\cs_new:Npn \__luatexcn_to_dimen:n #1
  {
    \lua_now:e {
      local~res~=~vertical_constants.to_dimen([=[\luaescapestring{#1}]=])~
      if~type(res)~==~"table"~and~res.unit~==~"em"~then~
        local~f~=~font.getfont(font.current())~
        res~=~math.floor(res.value~*~(f~and~f.size~or~655360)~+~0.5)~
      end~
      tex.sprint(res~or~0)
    }~sp
  }

% Helper function: Convert named color or raw RGB to normalized RGB string
% #1 = input color variable (tl)
% #2 = output RGB variable (tl)
\cs_new_protected:Npn \__luatexcn_color_to_rgb:NN #1 #2
  {
    \cs_if_exist:cTF { color @ #1 }
      {
        \exp_args:NV \extractcolorspec #1 \l_tmpa_tl
        \exp_args:NNx \convertcolorspec \l_tmpa_tl {rgb} \l_tmpb_tl
        \tl_set:Nx #2 { \l_tmpb_tl }
      }
      { \tl_set_eq:NN #2 #1 }
    \tl_replace_all:Nnn #2 { , } { ~ }
  }

% Helper function: Convert color to RGB, or set to "nil" if input is empty
% #1 = input color variable (tl)
% #2 = output RGB variable (tl)
\cs_new_protected:Npn \__luatexcn_color_to_rgb_or_nil:NN #1 #2
  {
    \tl_if_empty:NTF #1
      { \tl_set:Nn #2 { nil } }
      { \__luatexcn_color_to_rgb:NN #1 #2 }
  }

% ============================================================================
% Template Loading Helpers
% ============================================================================
\RequirePackage{core/luatex-cn-core-template}

\ExplSyntaxOff

\endinput
