% \iffalse meta-comment
% dtx/mahjong-tiles-03-tuples.dtx -- tuple helpers for mahjong-tiles
%
% Copyright (c) 2021 Daniel Schmitz
% Copyright (c) 2026 Lilia Chen May Wither
%
% This file is distributed under the MIT Licence; see LICENCE.
% \fi
%
% \subsection{Tuple helpers}
%
%    \begin{macrocode}
%<*package>
% -----------------------------------------------------------------------------
% Tuple helpers
% Pending tuple: {face}{orientation}{overlay}
% Output tuple:  {kind}{a}{b}{c}{overlay}
%   tile = {tile}{face}{suit}{orientation}{overlay}; suit may be m, p, s, z, f, or empty for x and ?
%   akastack = {akastack}{suit}{level}{ }{overlay}; red-five edge stack
%   draw = {draw}{face}{suit}{ }{ }; drawn tile rendered sideways above the hand row
%   gap  = {gap}{n}{ }{ }{ }; n means n/7 of one tile width
% -----------------------------------------------------------------------------
\cs_new_protected:Npn \__mahjongtiles_pending_put:nn #1#2
  { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#2} { } } }

\cs_new_protected:Npn \__mahjongtiles_tile_put:nnnn #1#2#3#4
  {
    \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#1} {#2} {#3} {#4} }
    \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool
  }
\cs_new_protected:Npn \__mahjongtiles_tile_put:nnn #1#2#3
  { \__mahjongtiles_tile_put:nnnn {#1} {#2} {#3} { } }
\cs_generate_variant:Nn \__mahjongtiles_tile_put:nnn { Vnn }
\cs_generate_variant:Nn \__mahjongtiles_tile_put:nnnn { Vnnn }

\cs_new_protected:Npn \__mahjongtiles_tile_put_aka_aware:nnnn #1#2#3#4
  {
    % Keep the source face in the parse tuple.  This lets postfix edge syntax
    % such as 0p""" force red fives even when aka=0; ordinary rendering still
    % maps 0m/0p/0s to regular fives when aka=0.
    \__mahjongtiles_tile_put:nnnn {#1} {#2} {#3} {#4}
  }
\cs_new_protected:Npn \__mahjongtiles_tile_put_aka_aware:nnn #1#2#3
  { \__mahjongtiles_tile_put_aka_aware:nnnn {#1} {#2} {#3} { } }
\cs_generate_variant:Nn \__mahjongtiles_tile_put_aka_aware:nnn { Vnn }
\cs_generate_variant:Nn \__mahjongtiles_tile_put_aka_aware:nnnn { Vnnn }

\cs_new_protected:Npn \__mahjongtiles_akastack_put:nnn #1#2#3
  {
    \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { akastack } {#1} {#2} { } {#3} }
    \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool
  }

\cs_new_protected:Npn \__mahjongtiles_gap_put:n #1
  {
    \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { gap } {#1} { } { } { } }
    \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool
  }

\cs_new_protected:Npn \__mahjongtiles_draw_put:nn #1#2
  {
    \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { draw } {#1} {#2} { } { } }
    \bool_set_false:N \l__mahjongtiles_last_concealed_kong_tail_bool
  }
\cs_generate_variant:Nn \__mahjongtiles_draw_put:nn { VV }


\cs_new_protected:Npn \__mahjongtiles_pending_set_last_stack_marker:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_stack_marker_aux:nnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} }
  }
\cs_new_protected:Npn \__mahjongtiles_pending_set_last_stack_marker_aux:nnnn #1#2#3#4
  {
    \str_if_eq:nnTF {#1} {0}
      {
        \int_case:nnF {#2}
          {
            {0} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {3} {#3} } }
            {3} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {4} {#3} } }
            {4} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {5} {#3} } }
            {5} { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {5} {#3} } }
          }
          { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {2} {#3} } }
      }
      { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {2} {#3} } }
  }

\cs_new_protected:Npn \__mahjongtiles_pending_set_last_orientation:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_orientation_aux:nnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} }
  }
\cs_new_protected:Npn \__mahjongtiles_pending_set_last_orientation_aux:nnnn #1#2#3#4
  { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#4} {#3} } }


\cs_new_protected:Npn \__mahjongtiles_output_apply_stack_marker:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_output_apply_stack_marker_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} }
  }
\cs_new_protected:Npn \__mahjongtiles_output_apply_stack_marker_aux:nnnnnn #1#2#3#4#5#6
  {
    \str_case:nnF {#1}
      {
        { tile }
          {
            \str_if_eq:nnTF {#2} {0}
              {
                \tl_if_in:nnTF { mps } {#3}
                  { \__mahjongtiles_akastack_put:nnn {#3} {1} {#5} }
                  { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {2} {#5} } }
              }
              { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {2} {#5} } }
          }
        { akastack }
          {
            \seq_put_right:Nn \l__mahjongtiles_tiles_seq
              { { akastack } {#2} { \int_min:nn {3} { #3 + 1 } } {#4} {#5} }
          }
      }
      {
        \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} }
        \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#6}
      }
  }

\cs_new_protected:Npn \__mahjongtiles_output_set_last_orientation:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_output_set_last_orientation_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#1} }
  }
\cs_new_protected:Npn \__mahjongtiles_output_set_last_orientation_aux:nnnnnn #1#2#3#4#5#6
  {
    \str_if_eq:nnTF {#1} { tile }
      { \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {#6} {#5} } }
      {
        \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} }
        \msg_error:nnn { mahjong-tiles } { missing-rotation-target } {#6}
      }
  }

\cs_new_protected:Npn \__mahjongtiles_set_last_orientation:n #1
  {
    \seq_if_empty:NTF \l__mahjongtiles_pending_seq
      { \__mahjongtiles_output_set_last_orientation:n {#1} }
      { \__mahjongtiles_pending_set_last_orientation:n {#1} }
  }

\cs_new_protected:Npn \__mahjongtiles_set_last_stack_marker:n #1
  {
    \seq_if_empty:NTF \l__mahjongtiles_pending_seq
      { \__mahjongtiles_output_apply_stack_marker:n {#1} }
      { \__mahjongtiles_pending_set_last_stack_marker:n {#1} }
  }

\cs_new_protected:Npn \__mahjongtiles_pending_set_last_overlay:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_pending_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_pending_set_last_overlay_aux:nnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#1} }
  }
\cs_new_protected:Npn \__mahjongtiles_pending_set_last_overlay_aux:nnnn #1#2#3#4
  { \seq_put_right:Nn \l__mahjongtiles_pending_seq { {#1} {#2} {#4} } }

\cs_new_protected:Npn \__mahjongtiles_output_set_last_overlay:n #1
  {
    \seq_pop_right:NNTF \l__mahjongtiles_tiles_seq \l__mahjongtiles_tmp_tl
      { \exp_last_unbraced:NV \__mahjongtiles_output_set_last_overlay_aux:nnnnnn \l__mahjongtiles_tmp_tl {#1} }
      { \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#1} }
  }
\cs_generate_variant:Nn \__mahjongtiles_output_set_last_overlay:n { V }
\cs_new_protected:Npn \__mahjongtiles_output_set_last_overlay_aux:nnnnnn #1#2#3#4#5#6
  {
    \str_case:nnF {#1}
      {
        { tile }
          {
            \tl_if_blank:nF {#6}
              {
                \bool_if:NT \l__mahjongtiles_last_concealed_kong_tail_bool
                  { \msg_warning:nnn { mahjong-tiles } { concealed-kong-overlay } {#6} }
              }
            \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { tile } {#2} {#3} {#4} {#6} }
          }
        { akastack }
          {
            \seq_put_right:Nn \l__mahjongtiles_tiles_seq { { akastack } {#2} {#3} {#4} {#6} }
          }
      }
      {
        \seq_put_right:Nn \l__mahjongtiles_tiles_seq { {#1} {#2} {#3} {#4} {#5} }
        \msg_error:nnn { mahjong-tiles } { missing-overlay-target } {#6}
      }
  }

\cs_new_protected:Npn \__mahjongtiles_set_last_overlay:n #1
  {
    \seq_if_empty:NTF \l__mahjongtiles_pending_seq
      { \__mahjongtiles_output_set_last_overlay:n {#1} }
      { \__mahjongtiles_pending_set_last_overlay:n {#1} }
  }

%</package>
%    \end{macrocode}
\endinput
