% ----------------------------------------------------------------------------
% the XSIM package - tags module
% 
%   eXercise Sheets IMproved
% 
% ----------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://github.com/cgnieder/xsim
% E-Mail: contact@mychemistry.eu
% ----------------------------------------------------------------------------
% Copyright 2017--2018 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
% 
% This work has the LPPL maintenance status `maintained'.
% 
% The Current Maintainer of this work is Clemens Niederberger.
% ----------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% ----------------------------------------------------------------------------
\XSIMmodule{tags}{tagging of exercises}

\xsim_load_modules:n {properties}

\seq_new:N \l__xsim_tag_types_seq
\bool_new:N \l____xsim_tagged_bool

\cs_new_protected:Npn \xsim_set_seq_from_clist:Nn #1#2
  {
    \seq_clear:N #1
    \clist_map_inline:nn {#2}
      { \tl_if_blank:nF {##1} { \seq_put_right:Nn #1 {##1} } }
  }
\cs_generate_variant:Nn \xsim_set_seq_from_clist:Nn {c,Nx}

\msg_new:nnn {xsim} {tag-exists}
  { The~ tag~ type~ `#1'~ already~ exists.~ I~ am~ doing~ nothing. }

% #1: name
\cs_new_protected:Npn \xsim_new_tag_type:n #1
  {
    \xsim_verbose:n { Declaring~ new~ tag~ type~ `#1'. }
    \seq_put_right:Nn \l__xsim_tag_types_seq {#1}
    \seq_remove_duplicates:N \l__xsim_tag_types_seq
    \seq_new:c  {l__xsim_chosen_tags_#1_seq}
    \bool_new:c {l__xsim_ignore_untagged_#1_bool}
    \bool_new:c {l____xsim_tagged_#1_bool}
    \keys_define:nn {xsim}
      {
        #1/ingore-untagged .bool_set:c = {l__xsim_ignore_untagged_#1_bool} ,
        #1/ignore-untagged .initial:n  = true ,
        #1                 .code:n     =
          \xsim_set_seq_from_clist:cn {l__xsim_chosen_tags_#1_seq} {##1}
      }
    \prg_new_protected_conditional:cpnn {xsim_if_#1_value:n} ##1 {T,F,TF}
      {
        \seq_if_in:cnTF {l__xsim_chosen_tags_#1_seq} {##1}
          { \prg_return_true: }
          { \prg_return_false: }
      }
    \xsim_declare_property:nnnn
      { \c_false_bool }
      { \c_false_bool }
      { \c_false_bool }
      {#1}
    \xsim_declare_printsolutions_condition:nn {#1}
      { \__xsim_printsolutions_if_tagged:nnnnTF {#1}  }
    \keys_define:nn {xsim/print-solutions}
      {
        #1         .choice: ,
        #1/false   .code:n    =
          \__xsim_printsolutions_condition:nn {#1} {false} ,
        #1/true    .code:n    =
          \__xsim_printsolutions_condition:nn {#1} {true} ,
        #1/unknown .code:n    =
          \keys_set:nn {xsim} { #1 = ##1 }
          \__xsim_printsolutions_condition:nn {#1} {true} ,
        #1         .initial:n = false
      }
  }

% #1: tag type
\prg_new_protected_conditional:Npnn \xsim_if_tag_type_exists:n #1 {T,F,TF}
  {
    \seq_if_in:NnTF \l__xsim_tag_types_seq {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }
  
% #1: tag type
% #2: exercise type
% #3: id
% #4: print|use
\prg_new_protected_conditional:Npnn
  \__xsim_printsolutions_if_tagged:nnnn #1#2#3#4 {T,F,TF}
  {
    \xsim_if_in_list:nnTF {#4} {#2-#3=={true}}
      {
        \__xsim_printsolutions_if_condition:nTF {#1}
          {
            \__xsim_printsolutions_condition_true:
            \xsim_if_tagged:nnnTF {#2} {#3} {#1}
              { \prg_return_true: }
              { \prg_return_false: }
          }
          { \prg_return_false: }
      }
      { \prg_return_false: }
  }

% #1: exercise type
% #2: id
% #3: tag type
\prg_new_protected_conditional:Npnn \xsim_if_tagged:nnn #1#2#3 {T,F,TF}
  {
    \bool_set_false:c {l____xsim_tagged_#3_bool}
    \seq_if_empty:cTF {l__xsim_chosen_tags_#3_seq}
      { \bool_set_true:c {l____xsim_tagged_#3_bool} }
      {
        \xsim_set_seq_from_clist:Nx
          \l__xsim_tmpa_seq
          { \xsim_get_property:nnn {#1} {#2} {#3} }
        \seq_if_empty:NTF \l__xsim_tmpa_seq
          {
            \bool_set_eq:cc
              {l____xsim_tagged_#3_bool}
              {l__xsim_ignore_untagged_#3_bool}
          }
          {
            \seq_map_inline:Nn \l__xsim_tmpa_seq
              {
                \seq_if_in:cnT {l__xsim_chosen_tags_#3_seq} {##1}
                  {
                    \bool_set_true:c {l____xsim_tagged_#3_bool}
                    \seq_map_break:
                  }
              }
          }
      }
    \bool_if:cTF {l____xsim_tagged_#3_bool}
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1: exercise type
% #2: id
\prg_new_protected_conditional:Npnn \xsim_if_tagged:nn #1#2 {T,F,TF}
  {
    \bool_set_true:N \l____xsim_tagged_bool
    \seq_map_inline:Nn \l__xsim_tag_types_seq
      {
        \xsim_if_tagged:nnnF {#1} {#2} {##1}
          {
            \bool_set_false:N \l____xsim_tagged_bool
            \seq_map_break:
          }
      }
    \bool_if:NTF \l____xsim_tagged_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }


% #1: exercise type
% #2: id
% #3: tag type
% #4: code
\cs_new_protected:Npn \xsim_foreach_exercise_tag:nnnn #1#2#3#4
  {
    \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
      { \xsim_get_property:nnn {#1} {#2} {#3} }
    \seq_map_inline:Nn \l__xsim_tmpa_seq {#4}
  }
\cs_generate_variant:Nn \xsim_foreach_exercise_tag:nnnn {oo}

% #1: exercise type
% #2: id
% #3: tag type
% #4: sep
\cs_new_protected:Npn \xsim_exercise_tags_use:nnnn #1#2#3#4
  {
    \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
      { \xsim_get_property:nnn {#1} {#2} {#3} }
    \seq_use:Nn \l__xsim_tmpa_seq {#4}
  }
\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn {oo}

% #1: exercise type
% #2: id
% #3: tag type
% #4: sep between two
% #5: sep between more than two
% #6: sep between last two
\cs_new_protected:Npn \xsim_exercise_tags_use:nnnnnn #1#2#3#4#5#6
  {
    \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
      { \xsim_get_property:nnn {#1} {#2} {#3} }
    \seq_use:Nnnn \l__xsim_tmpa_seq {#4} {#5} {#6}
  }
\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn   {oo}
\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnnnn {oo}

% ----------------------------------------------------------------------------
\file_input_stop:
