% \iffalse meta-comment
% An Infrastructure for Semantic Macros and Module Scoping
% Copyright (c) 2019 Michael Kohlhase, all rights reserved
%                this file is released under the
%                LaTeX Project Public License (LPPL)
% 
% The original of this file is in the public repository at 
% http://github.com/sLaTeX/sTeX/
%
% TODO update copyright  
%
%<*driver>
\providecommand\bibfolder{../../lib/bib}
\input{../../doc/stex-docheader}

\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{ \sTeX-References
% 	\thanks{Version {\fileversion} (last revised {\filedate})} 
% }
%
% \author{Michael Kohlhase, Dennis Müller\\
% 	FAU Erlangen-Nürnberg\\
% 	\url{http://kwarc.info/}
% }
%
% \maketitle
%
%\ifinfulldoc\else
% This is the documentation for the \pkg{stex-references} package.
% For a more high-level introduction, 
%  see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the
% \href{\basedocurl/stex.pdf}{full \sTeX documentation}.
% \fi
%
% \begin{documentation}\label{pkg:sref:doc}
%
% This sub package contains code related to links and cross-references
%
%\ifinfulldoc\else
% \input{../../doc/packages/stex-references}
% \fi
%
% \section{Macros and Environments}\label{pkg:sref:doc:macros}
%
% \begin{function}{\STEXreftitle}
%    \begin{syntax} \cs{STEXreftitle}\Arg{some title} \end{syntax}
%
%    Sets the title of the current document to \meta{some title}.
%    A reference to the current document from \emph{some other}
%    document will then be displayed accordingly. e.g.
%    if |\STEXreftitle{foo book}| is called, then referencing 
%    Definition 3.5 in this document in another document will display
%    |Definition 3.5 in foo book|.
% \end{function}
%
% \begin{function}{\stex_get_document_uri:}
%   Computes the current document uri from the current archive's
%   |narr|-field and its location relative to the archive's 
%   |source|-directory. Reference targets are computed from
%   this URI and the reference-id.
%
%   \begin{variable}{\l_stex_current_docns_str}
%      Stores its result in |\l_stex_current_docns_str|
%   \end{variable}
% \end{function}
%
% \begin{function}{\stex_get_document_url:}
%   Computes the current URL from the current archive's
%   |docurl|-field and its location relative to the archive's 
%   |source|-directory. Reference targets are computed from
%   this URL and the reference-id, if this document is only included
%   in SMS mode.
%
%   \begin{variable}{\l_stex_current_docurl_str}
%      Stores its result in |\l_stex_current_docurl_str|
%   \end{variable}
% \end{function}
%
% \subsection{Setting Reference Targets}
%
% \begin{function}{\stex_ref_new_doc_target:n}
%    \begin{syntax} \cs{stex_ref_new_doc_target:n}\Arg{id} \end{syntax}
%
%    Sets a new reference target with id \meta{id}.
% \end{function}
%
% \begin{function}{\stex_ref_new_sym_target:n}
%    \begin{syntax} \cs{stex_ref_new_sym_target:n}\Arg{uri} \end{syntax}
%
%    Sets a new reference target for the symbol \meta{uri}.
% \end{function}
%
% \subsection{Using References}
%
% \begin{function}{\sref}
%   \begin{syntax} \cs{sref}|[|\meta{opt-args}|]|\Arg{id} \end{syntax}
%   References the label with if \meta{id}.
%   Optional arguments: TODO
% \end{function}
%
% \begin{function}{\srefsym}
%   \begin{syntax} \cs{srefsym}|[|\meta{opt-args}|]|\Arg{symbol} \end{syntax}
%   Like \cs{sref}, but references the \emph{canonical label} for
%   the provided symbol. The canonical target is the last of the following
%   occuring in the document:
%   \begin{itemize}
%     \item A \cs{definiendum} or \cs{definame} for \meta{symbol},
%     \item The |sassertion|, |sexample| or |sparagraph| with |for=|\meta{symbol} that
%       generated \meta{symbol} in the first place, or
%     \item A \cs{sparagraph} with |type=symdoc| and |for=|\meta{symbol}.
%   \end{itemize}
% \end{function}
%
% \begin{function}{\srefsymuri}
%   \begin{syntax} \cs{srefsymuri}\Arg{URI}\Arg{text} \end{syntax}
%    A convenient short-hand for |\srefsym[linktext={text}]{URI}|,
%    but requires the first argument to be a full URI already.
%    Intended to be used in e.g. \cs{compemph@uri}, \cs{defemph@uri}, etc.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}\label{pkg:sref:impl}
%
% \section{\sTeX-References Implementation}
%
%    \begin{macrocode}
%<*package>

%%%%%%%%%%%%%   references.dtx   %%%%%%%%%%%%%

%<@@=stex_refs>
%    \end{macrocode}
%
% Warnings and error messages
%
%    \begin{macrocode}

%    \end{macrocode}
%
% References are stored in the file |\jobname.sref|, to enable
% cross-referencing external documents.
%
%    \begin{macrocode}
%\iow_new:N \c_@@_refs_iow
\AddToHook{begindocument}{
%  \iow_open:Nn \c_@@_refs_iow {\jobname.sref}
}
\AddToHook{enddocument}{
%  \iow_close:N \c_@@_refs_iow
}
%    \end{macrocode}
%
% \begin{macro}{\STEXreftitle}
%    \begin{macrocode}
\str_set:Nn \g_@@_title_tl {Unnamed~Document}

\NewDocumentCommand \STEXreftitle { m } {
  \tl_gset:Nx \g_@@_title_tl { #1 }
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Document URIs and URLs}
%
% \begin{variable}{\l_stex_current_docns_str}
%    \begin{macrocode}
\str_new:N \l_stex_current_docns_str
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\stex_get_document_uri:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_document_uri: {
  \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq
  \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str
  \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str
  \seq_get_left:NN \l_tmpb_seq \l_tmpb_str
  \seq_put_right:No \l_tmpa_seq \l_tmpb_str

  \str_clear:N \l_tmpa_str
  \prop_if_exist:NT \l_stex_current_repository_prop {
    \prop_get:NnNF \l_stex_current_repository_prop { narr } \l_tmpa_str {
      \prop_get:NnNF \l_stex_current_repository_prop { ns } \l_tmpa_str {}
    }
  }

  \str_if_empty:NTF \l_tmpa_str {
    \str_set:Nx \l_stex_current_docns_str { 
      file:/\stex_path_to_string:N \l_tmpa_seq
    }
  }{
    \bool_set_true:N \l_tmpa_bool
    \bool_while_do:Nn \l_tmpa_bool {
      \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str
      \exp_args:No \str_case:nnTF { \l_tmpb_str } {
        {source} { \bool_set_false:N \l_tmpa_bool }
      }{}{
        \seq_if_empty:NT \l_tmpa_seq {
          \bool_set_false:N \l_tmpa_bool
        }
      }
    }
  
    \seq_if_empty:NTF \l_tmpa_seq {
      \str_set_eq:NN \l_stex_current_docns_str \l_tmpa_str
    }{
      \str_set:Nx \l_stex_current_docns_str { 
        \l_tmpa_str/\stex_path_to_string:N \l_tmpa_seq
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\l_stex_current_docurl_str}
%    \begin{macrocode}
\str_new:N \l_stex_current_docurl_str
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\stex_get_document_url:}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_get_document_url: {
  \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq
  \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str
  \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str
  \seq_get_left:NN \l_tmpb_seq \l_tmpb_str
  \seq_put_right:No \l_tmpa_seq \l_tmpb_str

  \str_clear:N \l_tmpa_str
  \prop_if_exist:NT \l_stex_current_repository_prop {
    \prop_get:NnNF \l_stex_current_repository_prop { docurl } \l_tmpa_str {
      \prop_get:NnNF \l_stex_current_repository_prop { narr } \l_tmpa_str {
        \prop_get:NnNF \l_stex_current_repository_prop { ns } \l_tmpa_str {}
      }
    }
  }

  \str_if_empty:NTF \l_tmpa_str {
    \str_set:Nx \l_stex_current_docurl_str { 
      file:/\stex_path_to_string:N \l_tmpa_seq
    }
  }{
    \bool_set_true:N \l_tmpa_bool
    \bool_while_do:Nn \l_tmpa_bool {
      \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str
      \exp_args:No \str_case:nnTF { \l_tmpb_str } {
        {source} { \bool_set_false:N \l_tmpa_bool }
      }{}{
        \seq_if_empty:NT \l_tmpa_seq {
          \bool_set_false:N \l_tmpa_bool
        }
      }
    }
  
    \seq_if_empty:NTF \l_tmpa_seq {
      \str_set_eq:NN \l_stex_current_docurl_str \l_tmpa_str
    }{
      \str_set:Nx \l_stex_current_docurl_str { 
        \l_tmpa_str/\stex_path_to_string:N \l_tmpa_seq
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Setting Reference Targets}
%
%    \begin{macrocode}
\str_const:Nn \c_@@_url_str{URL}
\str_const:Nn \c_@@_ref_str{REF}
\str_new:N \l_@@_curr_label_str
% @currentlabel -> number
% @currentlabelname -> title
% @currentHref -> name.number <- id of some kind
% \theH# -> \arabic{section}
% \the#  -> number
% \hyper@makecurrent{#}
\int_new:N \l_@@_unnamed_counter_int
%    \end{macrocode}
%
% \begin{macro}{\stex_ref_new_doc_target:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_ref_new_doc_target:n {
  \stex_get_document_uri:
  \str_clear:N \l_@@_curr_label_str
  \str_set:Nx \l_tmpa_str { #1 }
  \str_if_empty:NT \l_tmpa_str {
    \int_incr:N \l_@@_unnamed_counter_int
    \str_set:Nx \l_tmpa_str {REF\int_use:N \l_@@_unnamed_counter_int}
  }
  \str_set:Nx \l_@@_curr_label_str {
    \l_stex_current_docns_str?\l_tmpa_str
  }
  \seq_if_exist:cF{g_@@_labels_\l_tmpa_str _seq}{
    \seq_new:c {g_@@_labels_\l_tmpa_str _seq}
  }
  \seq_if_in:coF{g_@@_labels_\l_tmpa_str _seq}\l_@@_curr_label_str {
    \seq_gput_right:co{g_@@_labels_\l_tmpa_str _seq}\l_@@_curr_label_str
  }
  \stex_if_smsmode:TF {
    \stex_get_document_url:
    \str_gset_eq:cN {sref_url_\l_@@_curr_label_str _str}\l_stex_current_docurl_str
    \str_gset_eq:cN {sref_\l_@@_curr_label_str _type}\c_@@_url_str
  }{
    %\iow_now:Nx \c_@@_refs_iow { \l_tmpa_str~=~\expandafter\unexpanded\expandafter{\@currentlabel}~in~\exp_args:No\unexpanded\g_@@_title_tl,}
    \exp_args:Nx\label{sref_\l_@@_curr_label_str}
    \immediate\write\@auxout{\stexauxadddocref{\l_stex_current_docns_str}{\l_tmpa_str}}
    \str_gset:cx {sref_\l_@@_curr_label_str _type}\c_@@_ref_str
  }
}
%    \end{macrocode}
% \end{macro}
%
% The following is used to set the necessary macros in the |.aux|-file.
%
%    \begin{macrocode}
\cs_new_protected:Npn \stexauxadddocref #1 #2 {
  \str_set:Nn \l_tmpa_str {#1?#2}
  \str_gset_eq:cN{sref_#1?#2_type}\c_@@_ref_str
  \seq_if_exist:cF{g_@@_labels_#2_seq}{
    \seq_new:c {g_@@_labels_#2_seq}
  }
  \seq_if_in:coF{g_@@_labels_#2_seq}\l_tmpa_str {
    \seq_gput_right:co{g_@@_labels_#2_seq}\l_tmpa_str
  }
}
%    \end{macrocode}
% To avoid resetting the same macros when the |.aux|-file is read
% at the end of the document:
%
%    \begin{macrocode}
\AtEndDocument{
  \def\stexauxadddocref#1 #2 {}{}
}
%    \end{macrocode}
%
% \begin{macro}{\stex_ref_new_sym_target:n}
%    \begin{macrocode}
\cs_new_protected:Nn \stex_ref_new_sym_target:n {
  \stex_if_smsmode:TF {
    \str_if_exist:cF{sref_sym_#1_type}{
      \stex_get_document_url:
      \str_gset_eq:cN {sref_sym_url_#1_str}\l_stex_current_docurl_str
      \str_gset_eq:cN {sref_sym_#1_type}\c_@@_url_str
    }
  }{
    \str_if_empty:NF \l_@@_curr_label_str {
      \str_gset_eq:cN {sref_sym_#1_label_str}\l_@@_curr_label_str
      \immediate\write\@auxout{
        \exp_not:N\expandafter\def\exp_not:N\csname sref_sym_#1_label_str\exp_not:N\endcsname{
            \l_@@_curr_label_str
          }
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Using References}
%
%    \begin{macrocode}
\str_new:N \l_@@_indocument_str
%    \end{macrocode}
%
% \begin{macro}{\sref}
% Optional arguments:
%    \begin{macrocode}

\keys_define:nn { stex / sref } {
  linktext      .tl_set:N  = \l_@@_linktext_tl ,
  fallback      .tl_set:N  = \l_@@_fallback_tl ,
  pre           .tl_set:N  = \l_@@_pre_tl ,
  post          .tl_set:N  = \l_@@_post_tl ,
}
\cs_new_protected:Nn \_@@_args:n {
  \tl_clear:N \l_@@_linktext_tl
  \tl_clear:N \l_@@_fallback_tl
  \tl_clear:N \l_@@_pre_tl
  \tl_clear:N \l_@@_post_tl
  \str_clear:N \l_@@_repo_str
  \keys_set:nn { stex / sref } { #1 }
}
%    \end{macrocode}
% The actual macro:
%    \begin{macrocode}
\NewDocumentCommand \sref { O{} m}{
  \_@@_args:n { #1 }
  \str_if_empty:NTF \l_@@_indocument_str {
    \str_set:Nx \l_tmpa_str { #2 }
    \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq ? \l_tmpa_str
    \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} = 1 {
      \seq_if_exist:cTF{g_@@_labels_\l_tmpa_str _seq}{
        \seq_get_left:cNF {g_@@_labels_\l_tmpa_str _seq} \l_tmpa_str {
          \str_clear:N \l_tmpa_str
        }
      }{
        \str_clear:N \l_tmpa_str
      }
    }{
      \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str
      \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str
      \int_set:Nn \l_tmpa_int { \exp_args:Ne \str_count:n {\l_tmpb_str?\l_tmpa_str} }
      \seq_if_exist:cTF{g_@@_labels_\l_tmpa_str _seq}{
        \str_set_eq:NN \l_tmpc_str \l_tmpa_str
        \str_clear:N \l_tmpa_str
        \seq_map_inline:cn {g_@@_labels_\l_tmpc_str _seq} {
          \str_if_eq:eeT { \l_tmpb_str?\l_tmpc_str }{
            \str_range:nnn { ##1 }{ -\l_tmpa_int}{ -1 } 
          }{
            \seq_map_break:n {
              \str_set:Nn \l_tmpa_str { ##1 }
            }
          }
        }
      }{
        \str_clear:N \l_tmpa_str
      }
    }
    \str_if_empty:NTF \l_tmpa_str {
      \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl
    }{
      \str_if_eq:cNTF {sref_\l_tmpa_str _type} \c_@@_ref_str {
        \tl_if_empty:NTF \l_@@_linktext_tl {
          \cs_if_exist:cTF{autoref}{
            \l_@@_pre_tl\exp_args:Nx\autoref{sref_\l_tmpa_str}\l_@@_post_tl
          }{
            \l_@@_pre_tl\exp_args:Nx\ref{sref_\l_tmpa_str}\l_@@_post_tl
          }
        }{
          \ltx@ifpackageloaded{hyperref}{
            \hyperref[sref_\l_tmpa_str]\l_@@_linktext_tl
          }{
            \l_@@_linktext_tl
          }
        }
      }{
        \ltx@ifpackageloaded{hyperref}{
          \href{\use:c{sref_url_\l_tmpa_str _str}}{\tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl}
        }{
          \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl
        }
      }
    }
  }{
    % TODO
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\srefsym}
%    \begin{macrocode}
\NewDocumentCommand \srefsym { O{} m}{
  \stex_get_symbol:n { #2 }
  \_@@_sym_aux:nn{#1}{\l_stex_get_symbol_uri_str}
}

\cs_new_protected:Nn \_@@_sym_aux:nn {
  \str_if_exist:cTF {sref_sym_#2 _label_str }{
    \sref[#1]{\use:c{sref_sym_#2 _label_str}}
  }{
    \_@@_args:n { #1 }
    \str_if_empty:NTF \l_@@_indocument_str {
      \tl_if_exist:cTF{sref_sym_#2 _type}{
        % doc uri in \l_tmpb_str
        \str_set:Nx \l_tmpa_str {\use:c{sref_sym_#2 _type}}
        \str_if_eq:NNTF \l_tmpa_str \c_@@_ref_str {
          % reference
          \tl_if_empty:NTF \l_@@_linktext_tl {
            \cs_if_exist:cTF{autoref}{
              \l_@@_pre_tl\autoref{sref_sym_#2}\l_@@_post_tl
            }{
              \l_@@_pre_tl\ref{sref_sym_#2}\l_@@_post_tl
            }
          }{
            \ltx@ifpackageloaded{hyperref}{
              \hyperref[sref_sym_#2]\l_@@_linktext_tl
            }{
              \l_@@_linktext_tl
            }
          }
        }{
          % URL
          \ltx@ifpackageloaded{hyperref}{
            \href{\use:c{sref_sym_url_#2 _str}}{\tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl}
          }{
            \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl
          }
        }
      }{
        \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl
      }
    }{
      % TODO
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\srefsymuri}
%    \begin{macrocode}
\cs_new_protected:Npn \srefsymuri #1 #2 {
  \_@@_sym_aux:nn{linktext={#2}}{#1}
}
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
