\NeedsTeXFormat{LaTeX2e}
\ProvidesExplPackage{PrimeTeX/packages/CrossRef}{2025-09-16}{1.0}{
	Custom label and reference commands.
}
%<@@=CrossRef>

\debug_on:n {all}

\prop_const_from_keyval:Nn \c_@@_section_names_prop {
	1 = Part\nobreakspace,
	2 = Chapter\nobreakspace,
	3 = Section\nobreakspace,
	4 = Subsection\nobreakspace,
	5 = Sub-subsection\nobreakspace,
	6 = Paragraph\nobreakspace,
	7 = Subparagraph\nobreakspace,
	8 = Appendix\nobreakspace,
}

\prop_const_from_keyval:Nn \c_@@_section_levels_prop {
	part			= 0,
	chapter			= 1,
	section			= 2,
	subsection		= 3,
	subsubsection	= 4,
	paragraph		= 5,
	subparagraph	= 6,
}

\str_const:Nn \c_@@_label_delimiter_str {/}
\str_const:Nn \c_@@_label_parent_str {.}
\str_const:Nn \c_@@_label_wildcard_str {~}
\str_const:Nn \c_@@_appendices_label_str {appendices}

\seq_new:N \g_@@_label_seq
\seq_gclear:N \g_@@_label_seq

\NewDocumentCommand{\Part}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {part} {#1} {#2} {#3} {#4}
	\RenewDocumentCommand{\parttitle}{}{#3}
}

\NewDocumentCommand{\Chapter}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {chapter} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Section}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {section} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Subsection}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {subsection} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Subsubsection}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {subsubsection} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Paragraph}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {paragraph} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Subparagraph}{s t^ m >{\TrimSpaces}m}{
	\@@_heading:nnnnn {subparagaph} {#1} {#2} {#3} {#4}
}

\NewDocumentCommand{\Appendices}{}{
	\@@_heading:nnnnn {part} {\c_true_bool} {\c_false_bool} {Appendices} {\c_@@_appendices_label_str}
}

\NewDocumentCommand{\GetCurrentLabel}{}{
	\seq_use:Nn \g_@@_label_seq {\c_@@_label_delimiter_str}
}

\NewDocumentCommand{\SetCurrentLabel}{
	% #1: Delimiter
	O{\c_@@_label_delimiter_str}
	% #2: Label string.
	>{\TrimSpaces}m
}{
	\seq_set_split:Nnn \g_@@_label_seq {#1} {#2}
}

\RenewDocumentCommand{\Ref}{
	% #1: Star (No star = include section name in reference, star = do not include).
	s
	% #2: Label string delimiter (defaults to "/").
	O{\c_@@_label_delimiter_str}
	% #3: Label Reference
	>{\TrimSpaces}m
	% #4: Parent label symbol (defaults to ".").
	O{\c_@@_label_parent_str}
	% #5: Label wildcard symbol (defaults to "~").
	O{\c_@@_label_wildcard_str}
}{ \group_begin:
	% Put the parameters in string variables so we can work with them.
	\str_const:Nn \c_@@_label_delimiter_str {#2}
	\str_const:Nn \c_@@_label_parent_str {#4}
	\str_const:Nn \c_@@_label_wildcard_str {#5}
	\str_const:Ne \c_@@_regex_str {
		% MATCH delimiter, parent, and wildcard symbols, but CAPTURE only
		% parents and wildcards, NOT delimiters.
		/|(\c_@@_label_parent_str|\c_@@_label_wildcard_str)
	}

	\seq_new:N \l_@@_label_seq
	\seq_new:N \l_@@_ref_seq

	\str_new:N \l_@@_ref_str
	\str_set:Nn \l_@@_ref_str {#3}

	% Split the string on the delimiters.
	\seq_set_regex_split:NNn \l_@@_ref_seq \c_@@_regex_str {\l_@@_ref_str}

	% Copy the current label sequence to a local variable.
	\seq_set_eq:NN \l_@@_label_seq \g_@@_label_seq

	% Iterate through the reference sequence, removing one element from the
	% end of the temporary label sequence for each parent symbol.
	\seq_map_indexed_function:NN \l_@@_ref_seq \_seq_map:nn

	% 	% Add the shortened temporary label sequence to the beginning of the
	% 	% reference sequence.
	\seq_concat:NNN \l_@@_ref_seq \l_@@_label_seq \l_@@_ref_seq

	% 	% Join the reference sequence back into a delimited string.
	\str_set:Nn \l_@@_ref_str {\seq_use:Nn \l_@@_ref_seq {#1}}

	\str_if_eq:nnF {\str_head:N \l_@@_ref_str} {\c_@@_label_delimiter_str} {
		\str_put_left:Nn \l_@@_ref_str {\c_@@_label_delimiter_str}
	}

	% Output the section name only if no star is passed.
	\bool_if:nF {#1} {
		\str_if_eq:nnTF {\seq_item:Nn \l_@@_ref_seq {1}} {\c_@@_appendices_label_str} {
			% If the part label is "appendices", the section name is "Appendix".
			\prop_item:Nn \c_@@_section_names_prop {9}
		}{
			% Otherwise, look up the correct section name.
			\prop_item:Nn \c_@@_section_names_prop {\seq_count:N \l_@@_ref_seq - 1}
		}
	}
	% Create a reference with the string we just created.
	\ref{\l_@@_ref_str}

	\cs_new:Nn \_seq_map:nn {
		\str_case:nn {#2} {
			{\c_@@_label_parent_str} {
				\seq_pop_right:NN \l_@@_label_seq \l_@@_tmpa_tl
				\seq_pop_left:NN \l_@@_ref_seq \l_@@_tmpa_tl
			}
			{\c_@@_label_wildcard_str} {
				\seq_pop_left:NN \l_@@_label_seq \l_@@_tmpa_tl
				\l_@@_tmpa_tl
			}
		}
	}
\group_end: }

\int_new:N \l_@@_current_level_int
\int_new:N \l_@@_pop_count_int
\int_new:N \l_@@_pop_index_int

\seq_new:N \l_@@_label_seq

\str_new:N \l_@@_label_str

\cs_new:Nn \@@_heading:nnnnn { \group_begin:
	% #1: Section name: part, chapter, section, etc.
	% #2: Star (passed to default sectioning command)
	% #3: ^ token: suppresses sectioning command.
	% #4: Section title
	% #5: Label

\debug_on:n {all}

	% Get the numeric level of the section command.
	\prop_get:NnN \c_@@_section_levels_prop {#1} \l_@@_current_level_int

	% \message{^^J@@_heading:~#5~\seq_use:Ne \g_@@_label_seq {\c_@@_label_delimiter_str}}

	\seq_set_eq:NN \l_@@_label_seq \g_@@_label_seq

	\int_set:Nn \l_@@_pop_count_int {
		\seq_count:N \l_@@_label_seq - \l_@@_current_level_int
	}

	\int_while_do:nNnn {\l_@@_pop_index_int} < {\l_@@_pop_count_int} {
		\seq_if_empty:NF \l_@@_label_seq {
			\seq_pop_right:NN \l_@@_label_seq \l_tmpa_tl
		}
		\int_incr:N \l_@@_pop_index_int
	}

	% Add the new label to the end of the modified label sequence.
	\seq_put_right:Ne \l_@@_label_seq {#5}

	\seq_gset_eq:NN \g_@@_label_seq \l_@@_label_seq

	% Join the label sequence into a string.
	\str_set:Ne \l_@@_label_str {
		\seq_use:Ne \l_@@_label_seq {\c_@@_label_delimiter_str}
	}

	% Add a delimiter to the beginning of the label string to indicate this is
	% an absolute reference.
	\str_put_left:Ne \l_@@_label_str {\c_@@_label_delimiter_str}

	% If the caret argument is NOT present, output the heading.
	\bool_if:nF {#3} {
		% Pass along the star argument if it is present.
		\bool_if:nTF {#2} {
			\use:c {#1} * {#4}
		} {
			\use:c {#1} {#4}
		}
	}
	% Output the label.
	\exp_args:Ne \label {\l_@@_label_str}
\group_end: }

\debug_off:n {all}