% --------------------------------------------------------------------------
% the LEADSHEETS package
% 
%   typesetting leadsheets and songbooks
%
% --------------------------------------------------------------------------
% Clemens Niederberger
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2014--2022 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.
% --------------------------------------------------------------------------
\LeadsheetsExplLibrary{properties}{2016/05/18 song properties}

\cs_generate_variant:Nn \tl_if_eq:nnTF {x}

\seq_new:N   \l__leadsheets_song_properties_seq
\prop_new:N  \l__leadsheets_duplicate_properties_prop

\cs_new_protected:Npn \leadsheets_define_property:n #1
  {
    \prop_new:c {l__leadsheets_songs_#1_prop}
    \seq_put_right:Nn \l__leadsheets_song_properties_seq {#1}
  }

\cs_new_protected:Npn \leadsheets_set_property:nnn #1#2#3
  {
    \tl_set_rescan:Nnn \l__leadsheets_tmpa_tl
      { \char_set_catcode_other:N \# }
      {#3}
    \prop_gput:cnV {l__leadsheets_songs_#2_prop} {#1}
      \l__leadsheets_tmpa_tl
  }
\cs_generate_variant:Nn \leadsheets_set_property:nnn { nnx }

\cs_new:Npn \leadsheets_get_property:nn #1#2
  { \prop_item:cn {l__leadsheets_songs_#2_prop} {#1} }
\cs_generate_variant:Nn \leadsheets_get_property:nn { V }

\prg_new_conditional:Npnn \leadsheets_if_property:nn #1#2 {p,T,F,TF}
  {
    \prop_if_in:cnTF {l__leadsheets_songs_#2_prop} {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }
\cs_generate_variant:Nn \leadsheets_if_property:nnTF { V }
\cs_generate_variant:Nn \leadsheets_if_property:nnT  { V }
\cs_generate_variant:Nn \leadsheets_if_property_p:nn { V }

\prg_new_protected_conditional:Npnn \leadsheets_if_any_property:nn #1#2 {T,F,TF}
  {
    \bool_set_false:N \l__leadsheets_tmpa_bool
    \clist_map_inline:nn {#1}
      {
        \prop_if_in:cnT {l__leadsheets_songs_#2_prop} {#1}
          { \bool_set_true:N \l__leadsheets_tmpa_bool }
      }
    \bool_if:NTF \l__leadsheets_tmpa_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }
\cs_generate_variant:Nn \leadsheets_if_any_property:nnTF {V}

\prg_new_protected_conditional:Npnn \leadsheets_if_all_properties:nn #1#2 {T,F,TF}
  {
    \bool_set_false:N \l__leadsheets_tmpa_bool
    \clist_map_inline:nn {#1}
      {
        \prop_if_in:cnTF {l__leadsheets_songs_#2_prop} {#1}
          { \bool_set_true:N \l__leadsheets_tmpa_bool }
          { \bool_set_false:N \l__leadsheets_tmpa_bool }
      }
    \bool_if:NTF \l__leadsheets_tmpa_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }
\cs_generate_variant:Nn \leadsheets_if_all_properties:nnTF {V}

\prg_new_protected_conditional:Npnn \leadsheets_if_properties_eq:nnn #1#2#3 {T,F,TF}
  {
    \tl_if_eq:xxTF
      { \leadsheets_get_property:nn {#1} {#2} }
      { \leadsheets_get_property:nn {#1} {#3} }
      { \prg_return_true: }
      { \prg_return_false: }
  }
\cs_generate_variant:Nn \leadsheets_if_properties_eq:nnnTF { V }

\prg_new_protected_conditional:Npnn \leadsheets_if_property_eq:nnn #1#2#3 {T,F,TF}
  {
    \tl_if_eq:xnTF
      { \leadsheets_get_property:nn {#1} {#2} }
      { #3 }
      { \prg_return_true: }
      { \prg_return_false: }
  }
\cs_generate_variant:Nn \leadsheets_if_property_eq:nnnTF { V }

\cs_new_protected:Npn \leadsheets_copy_property:nnn #1#2#3
  {
    \bool_if:nT
      {
        !\leadsheets_if_property_p:nn {#1} {#3}
        &&
        \leadsheets_if_property_p:nn {#1} {#2}
      }
      {
        \leadsheets_set_property:nnx {#1} {#3}
          { \leadsheets_get_property:nn {#1} {#2} }
      }
  }

\cs_new_protected:Npn \leadsheets_duplicate_property:nn #1#2
  { \prop_put:Nnn \l__leadsheets_duplicate_properties_prop {#1} {#2} }

\cs_new_protected:Npn \leadsheets_set_duplicate_properties:n #1
  {
     \prop_map_inline:Nn \l__leadsheets_duplicate_properties_prop
       { \leadsheets_copy_property:nnn {#1} {##1} {##2} }
  }

\cs_new_protected:Npn \leadsheets_print_property_list:nnnnnn #1#2#3#4#5#6
  {
    \seq_set_split:Nnx \l__leadsheets_tmpa_seq {~and~}
      { \leadsheets_get_property:nn {#1} {#2} }
    \seq_clear:N \l__leadsheets_tmpb_seq
    \seq_map_inline:Nn \l__leadsheets_tmpa_seq
      { \seq_put_right:Nn \l__leadsheets_tmpb_seq { #3 {##1} } }
    \seq_use:Nnnn \l__leadsheets_tmpb_seq {#4} {#5} {#6}
  }
\cs_generate_variant:Nn \leadsheets_print_property_list:nnnnnn { V }

\cs_new_protected:Npn \leadsheets_use_property_list:nnnn #1#2#3#4
  {
    \seq_set_split:Nnx \l__leadsheets_tmpa_seq {~and~}
      { \leadsheets_get_property:nn {#1} {#2} }
    \seq_clear:N \l__leadsheets_tmpb_seq
    \seq_map_inline:Nn \l__leadsheets_tmpa_seq
      { \seq_put_right:Nn \l__leadsheets_tmpb_seq { #3 {##1} } }
    \seq_use:Nn \l__leadsheets_tmpb_seq {#4}
  }
\cs_generate_variant:Nn \leadsheets_use_property_list:nnnn { V }

\cs_new:Npn \leadsheets_for_property_list:nn #1#2
  { \__leadsheets_for_property_list_aux:nww {#2} #1 ~and~ \q_stop }
\cs_generate_variant:Nn \leadsheets_for_property_list:nn { f }

\cs_new:Npn \__leadsheets_for_property_list_aux:nww #1#2 ~and~ #3 \q_stop
  {
    #1 { #2 }
    \tl_if_blank:nF {#3}
      { \__leadsheets_for_property_list_aux:nww {#1} #3 \q_stop }
  }

\DeclareExpandableDocumentCommand \songproperty {m}
  { \leadsheets_get_property:Vn \l_leadsheets_current_song_id_tl {#1} }

% #1: command that formats every entry in list
% #2: property
% #3: separator between two
% #4: separator between more than tow
% #5: separator between last two
\NewDocumentCommand \printsongpropertylist {O{\use:n}mmmm}
  {
    \leadsheets_print_property_list:Vnnnnn \l_leadsheets_current_song_id_tl
      {#2} {#1} {#3} {#4} {#5}
  }

% #1: command that formats every entry in list
% #2: property
% #3: separator
\NewDocumentCommand \usesongpropertylist {O{\use:n}mm}
  {
    \leadsheets_use_property_list:Vnnn \l_leadsheets_current_song_id_tl
      {#2} {#1} {#3}
  }

% #1: command that formats every entry in list
% #2: property
\DeclareExpandableDocumentCommand \forsongpropertylist {mm}
  {
    \leadsheets_for_property_list:fn
      { \leadsheets_get_property:Vn \l_leadsheets_current_song_id_tl {#1} }
       {#2}
  }

\DeclareExpandableDocumentCommand \ifsongproperty {m}
  { \leadsheets_if_property:VnTF \l_leadsheets_current_song_id_tl {#1} }

\NewDocumentCommand \ifanysongproperty {m}
  { \leadsheets_if_any_property:VnTF \l_leadsheets_current_song_id_tl {#1} }

\NewDocumentCommand \ifallsongproperties {m}
  { \leadsheets_if_all_properties:VnTF \l_leadsheets_current_song_id_tl {#1} }
  
\DeclareExpandableDocumentCommand \ifsongmeasuring {}
  { \leadsheets_if_measuring:TF }

\NewDocumentCommand \ifsongpropertiesequal {mm}
  { \leadsheets_if_properties_eq:VnnTF \l_leadsheets_current_song_id_tl {#1} {#2} }

% #1: property 1
% #2: property 2
\NewDocumentCommand \ifsongpropertyequal {mm}
  { \leadsheets_if_property_eq:VnnTF \l_leadsheets_current_song_id_tl {#1} {#2} }

% #1: property
% #2: tokenlist
\NewDocumentCommand \definesongproperty {m}
  { \leadsheets_define_property:n {#1} }
\@onlypreamble\definesongproperty

\NewDocumentCommand \copysongproperty {mm}
  { \leadsheets_duplicate_property:nn {#1} {#2} }
\@onlypreamble\copysongproperty

\file_input_stop:

2015/07/05: enable usage of # in the key property
2016/05/18: new commands \ifanysongproperty and \ifallsongproperties
