% 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.

% ltc-cn-vbook.cls - A document class for modern vertical Chinese typesetting.
% Default: Modern vertical layout.

\RequirePackage{expl3}
\RequirePackage{l3keys2e}
\RequirePackage{core/luatex-cn-core-template}
\ProvidesExplClass {ltc-cn-vbook} {2026/08/07} {0.4.1} {Chinese Vertical Book Class}

% ============================================================================
% Variables
% ============================================================================

\tl_new:N \l_cn_vbook_initial_template_tl
\prop_new:N \g_cn_vbook_template_map_prop

% Template name mappings (Chinese -> Internal config name)
\prop_gset_from_keyval:Nn \g_cn_vbook_template_map_prop
  {
    % Reserved for future mappings, currently just matches filename suffix
  }

% ============================================================================
% Class Options
% ============================================================================

\keys_define:nn { cn-vbook / options }
  {
    unknown .code:n =
      {
        \tl_set_eq:NN \l_tmpa_tl \l_keys_key_tl
        % Look up Chinese name mapping
        \prop_get:NVNT \g_cn_vbook_template_map_prop \l_tmpa_tl \l_tmpb_tl
          { \tl_set_eq:NN \l_tmpa_tl \l_tmpb_tl }
        % First try template files, if not found pass to article
        \luatexcn_if_template_exist:VnTF \l_tmpa_tl { luatex-cn-vbook- }
          { \tl_set_eq:NN \l_cn_vbook_initial_template_tl \l_tmpa_tl }
          { \PassOptionsToClass { \l_tmpa_tl } { article } }
      }
  }

\ProcessKeysOptions { cn-vbook / options }
\LoadClass{article}

% ============================================================================
% Dependencies
% ============================================================================

\RequirePackage{geometry}
\RequirePackage{xcolor}
\RequirePackage{fontspec}
\RequirePackage{environ}
\RequirePackage{xparse}
\RequirePackage{eso-pic}
\RequirePackage{luatex-cn-core}
\RequirePackage{core/luatex-cn-footnote}

% ============================================================================
% Initialization
% ============================================================================

% Load default config
\InputIfFileExists{configs/luatex-cn-vbook-default.cfg}{}{
  \PackageWarning{ltc-cn-vbook}{Config~file~configs/luatex-cn-vbook-default.cfg~not~found}
}

% Apply initial template from class options
\tl_if_empty:NF \l_cn_vbook_initial_template_tl
  {
    \luatexcn_load_template:Vn \l_cn_vbook_initial_template_tl { luatex-cn-vbook- }
  }

% Apply font at end of class loading
\AtEndOfClass{
  \tl_if_empty:NT \l__luatexcn_content_font_name_tl
    { \ApplyAutoFont }
}

% Set natural layout mode as default for modern vertical books
\ExplSyntaxOff
\AtBeginDocument{
  \directlua{
    _G.content = _G.content or {}
    if not _G.content.layout_mode then
      _G.content.layout_mode = "natural"
      _G.content.inter_cell_gap = 2 * 65536
    end
  }
}
\ExplSyntaxOn

% ============================================================================
% Running Header + Page Number via eso-pic (shipout hook)
% ============================================================================
% Displays running header and page number on each page.
% Both on inner margin (binding side): header at top, page number at bottom.
%
% Layout:
%   Odd pages (right page):  left side — chapter title (top) + page number (bottom)
%   Even pages (left page):  right side — book name (top) + page number (bottom)
%
% Users can override by redefining \cnVbookPageNumberHook.

\tl_new:N \l_cn_vbook_page_number_x_tl
\tl_new:N \l_cn_vbook_page_number_y_tl
\tl_new:N \l_cn_vbook_header_y_tl

\keys_define:nn { cn-vbook / page }
  {
    page-number-x .tl_set:N = \l_cn_vbook_page_number_x_tl,
    page-number-x .initial:n = {3mm},

    page-number-y .tl_set:N = \l_cn_vbook_page_number_y_tl,
    page-number-y .initial:n = {52mm},

    header-y .tl_set:N = \l_cn_vbook_header_y_tl,
    header-y .initial:n = {52mm},
  }

% Sync positions to plain TeX dimensions for shipout hook use
\newdimen\cnVbookPageNumX
\newdimen\cnVbookPageNumY
\newdimen\cnVbookPageNumFontSize
\newdimen\cnVbookHeaderY
\newdimen\cnVbookHeaderFontSize

\cnVbookPageNumX=\l_cn_vbook_page_number_x_tl\relax
\cnVbookPageNumY=\l_cn_vbook_page_number_y_tl\relax
\cnVbookPageNumFontSize=\l__luatexcn_page_number_font_size_tl\relax
\cnVbookHeaderY=\l_cn_vbook_header_y_tl\relax
\cnVbookHeaderFontSize=\l__luatexcn_page_header_font_size_tl\relax

% Re-sync when pageSetup is called
\cs_new_protected:Npn \__cn_vbook_sync_page_num_dims:
  {
    \dim_set:Nn \cnVbookPageNumX { \l_cn_vbook_page_number_x_tl }
    \dim_set:Nn \cnVbookPageNumY { \l_cn_vbook_page_number_y_tl }
    \dim_set:Nn \cnVbookPageNumFontSize { \l__luatexcn_page_number_font_size_tl }
    \dim_set:Nn \cnVbookHeaderY { \l_cn_vbook_header_y_tl }
    \dim_set:Nn \cnVbookHeaderFontSize { \l__luatexcn_page_header_font_size_tl }
  }

% Hook into pageSetup to sync dimensions
\hook_gput_code:nnn { begindocument } { cn-vbook }
  { \__cn_vbook_sync_page_num_dims: }

% \skipHeader — mark current page to suppress header display (e.g. title page)
\NewDocumentCommand{\skipHeader}{}
  {
    \lua_now:n { _G.vbook_skip_header_page = true }
  }

% 中文别名
\NewCommandCopy{\跳过页眉}{\skipHeader}

\ExplSyntaxOff

% Default shipout hook: running header + page number
% Uses Lua to determine odd/even page and conditionally output TeX commands
\newcommand{\cnVbookPageNumberHook}{%
  \directlua{
    local pg = tex.count[0]
    local style = _G.page and _G.page.number_style or "none"
    local header_on = _G.page and _G.page.header_enabled or false
    local skip = _G.vbook_skip_header_page or false
    local show_number = (style ~= "none" and style ~= "")
    local show_header = header_on and not skip

    _G.vbook_skip_header_page = false

    if not show_number and not show_header then return end

    local is_odd = (math.fmod(pg, 2) == 1)

    local header_text = ""
    if show_header then
      local book = _G.metadata and _G.metadata.book_name or ""
      local chapter = _G.metadata and _G.metadata.chapter_title or ""
      header_text = is_odd and chapter or book
      if header_text == "" then show_header = false end
    end

    local pw_cmd = "\\paperwidth-\\cnVbookPageNumX-2em"
    if is_odd then
      if show_header then
        tex.sprint("\\AtPageUpperLeft{\\put(\\LenToUnit{\\cnVbookPageNumX},-\\LenToUnit{\\cnVbookHeaderY}){\\parbox[t]{2em}{\\centering\\fontsize{\\cnVbookHeaderFontSize}{13pt}\\selectfont\\DrawVerticalText{" .. header_text .. "}}}}")
      end
      if show_number then
        tex.sprint("\\AtPageLowerLeft{\\put(\\LenToUnit{\\cnVbookPageNumX},\\LenToUnit{\\cnVbookPageNumY}){\\parbox[b]{2em}{\\centering\\fontsize{\\cnVbookPageNumFontSize}{13pt}\\selectfont\\DrawVerticalPageNumber}}}")
      end
    else
      if show_header then
        tex.sprint("\\AtPageUpperLeft{\\put(\\LenToUnit{" .. pw_cmd .. "},-\\LenToUnit{\\cnVbookHeaderY}){\\parbox[t]{2em}{\\centering\\fontsize{\\cnVbookHeaderFontSize}{13pt}\\selectfont\\DrawVerticalText{" .. header_text .. "}}}}")
      end
      if show_number then
        tex.sprint("\\AtPageLowerLeft{\\put(\\LenToUnit{" .. pw_cmd .. "},\\LenToUnit{\\cnVbookPageNumY}){\\parbox[b]{2em}{\\centering\\fontsize{\\cnVbookPageNumFontSize}{13pt}\\selectfont\\DrawVerticalPageNumber}}}")
      end
    end
  }%
}

% Register shipout hook
\AddToShipoutPictureFG{%
  \cnVbookPageNumberHook
}

\pagestyle{empty}
\endinput
