%D \module
%D   [       file=mult-aux,
%D        version=2010.08.2,
%D          title=\CONTEXT\ Multilingual Macros,
%D       subtitle=Helpers,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% todo: setupxxx and setupxxxs (so a plural for the root setup and
% we can consider blocking the root)

% todo (e.g for columnsets and registers): \definexxx[parent][1]
%

%D A generalization of \MKIV-like inheritance. Just something to play
%D with (interface might change). The code here evolved in an email
%D exchange between me and Wolgang Schuster.

% todo: doifelse<whatever>

\writestatus{loading}{ConTeXt Multilingual Macros / Helpers}

\registerctxluafile{mult-aux}{1.001}

\unprotect

%D \starttyping
%D \unprotect
%D     \def\????aa{@@@@aa}
%D
%D     \installparameterhandler   \????aa {whatever}
%D     \installsetuphandler       \????aa {whatever}
%D     \installdefinehandler      \????aa {whatever} \????aa % #3 == defaultroot
%D     \installfontandcolorhandler\????aa {whatever}
%D
%D   % \installcommandhandler     \????aa {whatever} \????aa
%D \protect
%D
%D % \whateverparameter \c!test
%D % \whateverparameterhash \c!test
%D % \namedwhateverparameter \mycurrentwhatever \c!test
%D % \usewhateverstyleandcolor \c!style \c!color
%D % \everydefinewhatever (sets \currentwhatever)
%D % \everypresetwhatever (can be used to reset parameters as we can redefine)
%D % \everysetupwhatever (sets \currentwhatever)
%D
%D \starttext
%D     \definewhatever[first] \definewhatever[second][first]
%D                                           test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D     \setupwhatever        [method=unset]  test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D     \setupwhatever[first] [method=first]  test: \def\currentwhatever{first}  \whateverparameter{method} \par
%D                                           test: \def\currentwhatever{second} \whateverparameter{method} \par
%D     \setupwhatever[second][method=second] test: \def\currentwhatever{second} \whateverparameter{method} \par
%D \stoptext
%D \stoptyping

% problem: every* could clash
%
% There can be less {} in the following definitions if we assume \??aa and \c!somecs
%
% todo: \def\detokenized...parameter#1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2\endcsname}} % always root
%
% it might be more efficient to do this at the lua and
%
% watch the push/pop and predefinition of current .. this is needed for nested
% definitions and overloaded defines using the predefined one

% todo: add (relaxed) postsetup and postdefine hooks, just after the everys

% Start of experimental code: especially tables can have many assignments
% and although most time is spent in the typesetting anyway, we can squeeze
% out a little bit. Of course having 500 rows of 50 columns each with some
% setting does not happen that often. One should keep in mind that in the
% average document having some 500 assignments is no exception but there we're
% talking of neglectable runtime for them. Of course in the definitions below
% there is no real gain, only in the generated \setup* commands. Another
% situation with many assignments is \XML\ where we can pass attributes
% and normally don't do testing of them making sense.
%
% \testfeatureonce{100000}{\getparameters[bla][a=111,b=222,c=333]}% 1.669s
% \testfeatureonce{100000}{\mult_interfaces_get_parameters{bla} [a=111,b=222,c=333]}% 1.529s
% \testfeatureonce{100000}{\def\m_mult_interfaces_namespace{bla}\mult_interfaces_get_parameters_indeed[a=111,b=222,c=333]}% 1.466s

\let\m_mult_interfaces_namespace\empty

\def\mult_interfaces_get_parameters#1[#2%
  {\if\noexpand#2]%
     \expandafter\gobbleoneargument
   \else
     \def\m_mult_interfaces_namespace{#1}%
     \expandafter\mult_interfaces_get_parameters_indeed
   \fi#2}

\def\mult_interfaces_get_parameters_indeed#1]% namespace already set
  {\mult_interfaces_get_parameters_item#1,],\_e_o_p_}

\def\mult_interfaces_get_parameters_item#1,#2% #2 takes space before ,
  {\if,#1,% dirty trick for testing #1=empty
     \expandafter\mult_interfaces_get_parameters_item
   \else\if]#1%
     \doubleexpandafter\gobbleoneargument
   \else
     \mult_interfaces_get_parameters_assign#1==\empty\_e_o_p_
     \doubleexpandafter\mult_interfaces_get_parameters_item
   \fi\fi#2}

\def\mult_interfaces_get_parameters_error#1#2#3%
  {\showassignerror{#2}{\the\inputlineno\space(#1)}}

\def\mult_interfaces_get_parameters_assign#1=#2=#3#4\_e_o_p_
  {\ifx\empty#1\empty
     \expandafter\mult_interfaces_get_parameters_error
   \else\ifx#3\empty
     \doubleexpandafter\mult_interfaces_get_parameters_error
   \else
     \doubleexpandafter\dosetvalue
   \fi\fi
   \m_mult_interfaces_namespace{#1}{#2}}

\newif\ifassignment

\def\mult_check_for_assignment_indeed#1=#2#3\_end_
  {\if#2@\assignmentfalse\else\assignmenttrue\fi}

\def\mult_check_for_assignment#1%
  {\expandafter\mult_check_for_assignment_indeed\detokenize{#1}=@@\_end_}

% End of experimental code.

% the commented detokenized variant that backtracks ... needs testing usage first
%
% \let\whatever\relax
%
% \definetest[oeps][bagger=\whatever]
%
% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{bagger}}\meaning\hans\par
% \def\currenttest{oeps} \edef\hans{\detokenizedtestparameter{reggab}}\meaning\hans\par

\def\mult_interfaces_detokenize{\expandafter\expandafter\expandafter\detokenize\expandafter\expandafter\expandafter}

\unexpanded\def\mult_interfaces_install_parameter_handler#1#2#3#4#5#6#7#8#9% inlining \csname*\endcsname is more efficient (#3 and #6 only)
  {\ifx#2\relax\let#2\empty\fi                                             % it is hardly faster but produces less expansion tracing
  %\def#3##1{\csname#4{#1#2}{##1}\endcsname}%
   \def#3##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}%
   \def#4##1##2{\ifcsname##1:##2\endcsname##1:##2\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
   \def#5##1##2{\ifx##1\relax\s!empty\else#4{##1}{##2}\fi}% is {} needed around ##1 ?
   \def#6##1##2{\csname\ifcsname#1##1:##2\endcsname#1##1:##2\else\expandafter#5\csname#1##1:\s!parent\endcsname{##2}\fi\endcsname}%
   \def#7##1{\detokenize\expandafter\expandafter\expandafter{\csname#1#2:##1\endcsname}}% always root, no backtrack
 % \def#7##1{\mult_interfaces_detokenize{\csname#4{#1#2}{##1}\endcsname}}% compact version
 % \def#7##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
   \def#8##1{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\s!empty\fi\endcsname}%
   \def#9##1{\csname#1#2:##1\endcsname}}

\unexpanded\def\installparameterhandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_parameter_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname do#2parameter\endcsname           % or : #2_parameter_hash
        \expandafter\noexpand\csname do#2parentparameter\endcsname     % or : #2_parent_parameter_hash
        \expandafter\noexpand\csname named#2parameter\endcsname
        \expandafter\noexpand\csname detokenized#2parameter\endcsname
        \expandafter\noexpand\csname strict#2parameter\endcsname       % checked
        \expandafter\noexpand\csname direct#2parameter\endcsname}}     % unchecked

\unexpanded\def\mult_interfaces_install_root_parameter_handler#1#2#3%
  {\def#2##1{\detokenize\expandafter\expandafter\expandafter{\csname#1:##1\endcsname}}% always root
   \def#3##1{\csname\ifcsname#1:##1\endcsname#1:##1\else\s!empty\fi\endcsname}}

\unexpanded\def\installrootparameterhandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_root_parameter_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname detokenizedroot#2parameter\endcsname
        \expandafter\noexpand\csname root#2parameter\endcsname}}

\unexpanded\def\mult_interfaces_install_parameter_hash_handler#1#2#3#4#5#6#7#8#9%
  {\ifx#2\relax\let#2\empty\fi
   \def#3##1{#1#4{#1#2}{##1}:}% leading #1 was missing .. is this one used?
   \def#4##1##2{\ifcsname##1:##2\endcsname##1\else\expandafter#5\csname##1:\s!parent\endcsname{##2}\fi}%
   \def#5##1##2{\ifx##1\relax\else#4{##1}{##2}\fi}%
   \def#6{#1#2:}%
   \def#7##1{#1##1:}%
   \def#8{\ifx#2\empty\else\ifcsname#1#2:\s!parent\endcsname\else\expandafter\let\csname#1#2:\s!parent\endcsname#1\fi\fi}%
   \unexpanded\def#9##1{\expandafter\edef\csname#1##1:\s!parent\endcsname{#1#2}}}

\unexpanded\def\installparameterhashhandler#1#2%
  {\expandafter\let\csname#2namespace\endcsname#1%
   \normalexpanded
     {\mult_interfaces_install_parameter_hash_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameterhash\endcsname
        \expandafter\noexpand\csname do#2parameterhash\endcsname         % or : #2_parameter_hash
        \expandafter\noexpand\csname do#2parentparameterhash\endcsname   % or : #2_parent_parameter_hash
        \expandafter\noexpand\csname current#2hash\endcsname
        \expandafter\noexpand\csname named#2hash\endcsname
        \expandafter\noexpand\csname check#2parent\endcsname
        \expandafter\noexpand\csname chaintocurrent#2\endcsname}}

% In \MKIV\ we can probably use the english variant for all other
% languages too.

% todo: inline the \do*value

\unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
  {\ifx#2\relax\let#2\empty\fi
   \unexpanded\def#3{\dosetvalue {#1#2:}}%        ##1 {##2} (braces are mandate)
   \unexpanded\def#4{\dosetevalue{#1#2:}}%        ##1 {##2} (braces are mandate)
   \unexpanded\def#5{\doletvalue {#1#2:}}%        ##1 ##2
   \unexpanded\def#6{\doletvalue {#1#2:}\empty}}% ##1

\startinterface english

    \unexpanded\def\mult_interfaces_install_parameter_set_handler#1#2#3#4#5#6%
      {\ifx#2\relax\let#2\empty\fi
       \unexpanded\def#3##1{\expandafter \def\csname#1#2:##1\endcsname}%        ##1 {##2} (braces are mandate)
       \unexpanded\def#4##1{\expandafter\edef\csname#1#2:##1\endcsname}%        ##1 {##2} (braces are mandate)
       \unexpanded\def#5##1{\expandafter \let\csname#1#2:##1\endcsname}%        ##1 ##2
       \unexpanded\def#6##1{\expandafter \let\csname#1#2:##1\endcsname\empty}}% ##1

\stopinterface

\unexpanded\def\installparametersethandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_parameter_set_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname set#2parameter\endcsname
        \expandafter\noexpand\csname setexpanded#2parameter\endcsname
        \expandafter\noexpand\csname let#2parameter\endcsname
        \expandafter\noexpand\csname reset#2parameter\endcsname}}

\let\dousecurrentstyleparameter\relax
\let\dousecurrentcolorparameter\relax

\let\currentstyleparameter\empty
\let\currentcolorparameter\empty

\unexpanded\def\mult_interfaces_install_style_and_color_handler#1#2#3#4%
  {\unexpanded\def#2##1##2% style color
     {\edef\currentstyleparameter{#1{##1}}% this name is public
      \edef\currentcolorparameter{#1{##2}}% this name is public
      \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi
      \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}%
   \unexpanded\def#3##1% style
     {\edef\currentstyleparameter{#1{##1}}% this name is public
      \ifx\currentstyleparameter\empty\else\dousecurrentstyleparameter\fi}%
   \unexpanded\def#4##1% color
     {\edef\currentcolorparameter{#1{##1}}% this name is public
      \ifx\currentcolorparameter\empty\else\dousecurrentcolorparameter\fi}}

\unexpanded\def\installstyleandcolorhandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_style_and_color_handler
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname use#2styleandcolor\endcsname % maybe an alias use#2styleandcolorparameters
        \expandafter\noexpand\csname use#2styleparameter\endcsname
        \expandafter\noexpand\csname use#2colorparameter\endcsname}}

\let\definehandlerparent\empty

\def\mult_check_for_parent#1#2#3#4%
  {\ifcsname#1#4:\s!parent\endcsname \else \ifx#4\empty \else
     \writestatus\m!system{error: invalid parent #4 for #3, #4 defined too (best check it)}%
     \expandafter\edef\csname#1#4:\s!parent\endcsname{#2}%
   \fi \fi}

\unexpanded\def\mult_interfaces_install_define_handler#1#2#3#4#5#6#7#8#9% why is \expanded still needed in clones
  {\ifx#4\relax\let#4\empty\fi                                          % see \defineregister
   \unexpanded\def#2{\dotripleempty#5}%
   \newtoks#6%
   \newtoks#7%
   \unexpanded\def#5[##1][##2][##3]% [child][parent][settings] | [child][settings] | [child][parent] | [child]
     {\let#9#4%
      \edef#4{##1}%
      \ifthirdargument
        \the#6% predefine
        \edef#8{##2}%
        \mult_check_for_parent{#1}{#3}#4#8%
        \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
        \mult_interfaces_get_parameters{#1#4:}[##3]%
      \else\ifsecondargument
        \the#6% predefine
        \expandafter\mult_check_for_assignment_indeed\detokenize{##2}=@@\_end_
        \ifassignment
          \let#8\empty
          \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
          \mult_interfaces_get_parameters{#1#4:}[##2]%
        \else
          \edef#8{##2}%
          \mult_check_for_parent{#1}{#3}#4#8%
          \expandafter\edef\csname#1#4:\s!parent\endcsname{#1##2}%
        \fi
      \else
        \the#6% predefine
        \let#8\empty
        \expandafter\edef\csname#1#4:\s!parent\endcsname{#3}%
      \fi\fi
      \the#7%
      \let#4#9}}

\unexpanded\def\installdefinehandler#1#2#3%
  {\normalexpanded
     {\mult_interfaces_install_define_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname define#2\endcsname
        {\noexpand#3}% root
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname define_#2\endcsname % semi-public
        \expandafter\noexpand\csname everypreset#2\endcsname
        \expandafter\noexpand\csname everydefine#2\endcsname
        \expandafter\noexpand\csname current#2parent\endcsname
        \expandafter\noexpand\csname saved_defined_#2\endcsname}}

\unexpanded\def\mult_interfaces_install_setup_handler#1#2#3#4#5#6#7#8#9%
  {\ifx#3\relax\let#3\empty\fi
   \unexpanded\def#2{\dodoubleempty#4}%
   \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}% no every ! don't change it
   \newtoks#5%
   \newtoks#8%
   \unexpanded\def#4[##1][##2]% maybe helper
     {\let#7#3%
      \ifsecondargument
        \def#9####1% we will have a simple one as well
          {\edef#3{####1}%
           \mult_interfaces_get_parameters{#1#3:}[##2]%
           \the#5}%
        \processcommalist[##1]#9%
      \else
        \let#3\empty
        \mult_interfaces_get_parameters{#1:}[##1]%
        \the#5%
      \fi
      \let#3#7%
      \the#8}}

\unexpanded\def\installsetuphandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname setup_#2\endcsname % semi-public
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname everysetup#2root\endcsname
        \expandafter\noexpand\csname nested_setup_current#2\endcsname}}

\let\doingrootsetupnamed\plusone    % \setuplayout[name][key=value]
\let\doingrootsetuproot \plustwo    % \setuplayout      [key=value]
\let\doingrootsetnamed  \plusthree  % \setuplayout[name]
\let\doingrootsetroot   \plusfour   % \setuplayout

\unexpanded\def\mult_interfaces_install_switch_setup_handler_a#1#2#3#4#5%
  {\ifx#3\relax\let#3\empty\fi
   \unexpanded\def#2{\dodoubleempty#4}%
   \unexpanded\def#5{\mult_interfaces_get_parameters{#1#3:}}}

\unexpanded\def\mult_interfaces_install_switch_setup_handler_b#1#2#3#4#5#6#7#8#9%
  {\newtoks#5%
   \newconstant#2%
   \newtoks#8%
   \newtoks#9%
   \ifx#6\relax\let#6\empty\fi
   \unexpanded\def#4[##1][##2]% maybe helper
     {\ifsecondargument % no commalist here
        % \setuplayout[whatever][key=value]
        \let#7#3%
        \let#6#3%
        \edef#3{##1}%
        #2\doingrootsetupnamed
        \mult_interfaces_get_parameters{#1#3:}[##2]%
        \the#5%
        \ifx#3#6\the#8\fi % only switchsetups if previous == current
        \let#3#7%
      \else\iffirstargument
        % \mult_check_for_assignment{##1}%
          \expandafter\mult_check_for_assignment_indeed\detokenize{##1}=@@\_end_
        \ifassignment
          % \setuplayout[key=value]
          \let#7#3%
          \let#6#3%
          \let#3\empty
          #2\doingrootsetuproot
          \mult_interfaces_get_parameters{#1:}[##1]%
          \the#5%
          \the#8% switchsetups
          \let#3#7%
        \else
          % \setuplayout[whatever]
          \let#6#3%   % previous becomes current
          \edef#3{##1}% this will catch reset so one needs to test for it
          #2\doingrootsetnamed
          \the#5%     % we can check for previous vs current
          \the#8% switchsetups
        \fi
      \else
        % \setuplayout
        \let#6#3%      % previous becomes current
        \let#3\empty   % current becomes empty
        #2\doingrootsetroot
        \the#5%
        \the#8% switchsetups
      \fi\fi
      #2\zerocount % mode is always zero at the end
      \the#9}}

\unexpanded\def\installswitchsetuphandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_switch_setup_handler_a
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname setup_#2\endcsname % semi-public
        \expandafter\noexpand\csname setupcurrent#2\endcsname
      \mult_interfaces_install_switch_setup_handler_b
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname #2setupmode\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname setup_#2\endcsname % semi-public
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname previous#2\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname everyswitch#2\endcsname
        \expandafter\noexpand\csname everysetup#2root\endcsname}}

\unexpanded\def\mult_interfaces_install_auto_setup_handler#1#2#3#4#5#6#7#8#9%
  {\ifx#3\relax\let#3\empty\fi
   \unexpanded\def#2{\dotripleempty#4}%
   \unexpanded\def#6{\mult_interfaces_get_parameters{#1#3:}}%
   \newtoks#5%
   \def#4[##1][##2][##3]%
     {\let#8#3%
      \ifthirdargument
        \def#9####1%
          {\edef#3{####1}%
           \expandafter\def\csname#1#3:\s!parent\endcsname{#1##2}%
           \mult_interfaces_get_parameters{#1#3:}[##3]% always sets parent
           \the#5}%
        \processcommalist[##1]#9%
      \else\ifsecondargument
        \def#9####1%
          {\edef#3{####1}%
           #7% checks parent and sets if needed
           \mult_interfaces_get_parameters{#1#3:}[##2]%
           \the#5}%
        \processcommalist[##1]#9%
      \else
        \let#3\empty
        \mult_interfaces_get_parameters{#1:}[##1]%
        \the#5%
      \fi\fi
      \let#3#8}}

\unexpanded\def\installautosetuphandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_auto_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname setup_#2\endcsname % semi-public
        \expandafter\noexpand\csname everysetup#2\endcsname
        \expandafter\noexpand\csname setupcurrent#2\endcsname
        \expandafter\noexpand\csname check#2parent\endcsname
        \expandafter\noexpand\csname saved_setup_current#2\endcsname
        \expandafter\noexpand\csname nested_setup_current#2\endcsname}}

\unexpanded\def\installbasicparameterhandler#1#2%
  {\installparameterhandler    {#1}{#2}%
   \installparameterhashhandler{#1}{#2}%
   \installparametersethandler {#1}{#2}%
   \installrootparameterhandler{#1}{#2}}

\unexpanded\def\installbasicautosetuphandler#1#2#3% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installautosetuphandler     {#1}{#2}}

\unexpanded\def\installcommandhandler#1#2#3% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installsetuphandler         {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\unexpanded\def\installswitchcommandhandler#1#2#3% \??self name \??parent (can be \??self)
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installswitchsetuphandler   {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\unexpanded\def\installautocommandhandler#1#2#3% automatically defined cloned setups
  {\installbasicparameterhandler{#1}{#2}%
   \installdefinehandler        {#1}{#2}{#3}%
   \installautosetuphandler     {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

\unexpanded\def\installsimplecommandhandler#1#2#3% no define (experiment) - use \check*parent when defining
  {\installbasicparameterhandler{#1}{#2}%
   \installsetuphandler         {#1}{#2}%
   \installstyleandcolorhandler {#1}{#2}}

%D Many mechanisms have some kind of inheritance in place, and these are
%D the speed||critical ones. Therefore there is no reason to stick to
%D \type {\@@xxkey} for the sake of performance. For this reason we also
%D provide a direct variant. This permits a more consistent treatment of
%D namespaces. A \type {\whateverparameter} call is three times slower
%D and a \type {\directwhateverparameter} call two times but for some
%D 100K expansions we only loose some .1 second which is neglectable
%D given the small amount of expansions in real runs.

%D We don't need colons for such simple cases.

\unexpanded\def\mult_interfaces_install_direct_parameter_handler#1#2#3#4#5%
  {\def#3##1{\csname\ifcsname#1##1\endcsname#1##1\else\s!empty\fi\endcsname}%
   \def#4##1{\detokenize\expandafter\expandafter\expandafter{\csname#1##1\endcsname}}%
 % \def#4##1{\mult_interfaces_detokenize{\csname\ifcsname#1#2:##1\endcsname#1#2:##1\else\expandafter#5\csname#1#2:\s!parent\endcsname{##1}\fi\endcsname}}%
   \def#5##1{\csname#1##1\endcsname}}

\unexpanded\def\installdirectparameterhandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_direct_parameter_handler
        {\noexpand#1}%
        \expandafter\noexpand\csname current#2\endcsname
        \expandafter\noexpand\csname #2parameter\endcsname
        \expandafter\noexpand\csname detokenized#2parameter\endcsname
        \expandafter\noexpand\csname direct#2parameter\endcsname}}

\unexpanded\def\mult_interfaces_install_direct_setup_handler#1#2#3#4#5%
  {\unexpanded\def#2{\dosingleempty#3}%
   \newtoks#5%
   \def#3[##1]{\mult_interfaces_get_parameters#1[##1]\the#5}%
   \def#4{\mult_interfaces_get_parameters#1}}

\unexpanded\def\installdirectsetuphandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_direct_setup_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname setup#2\endcsname
        \expandafter\noexpand\csname setup_#2\endcsname % semi-public
        \expandafter\noexpand\csname setupcurrent#2\endcsname % no \every (we use 'current' for consistency)
        \expandafter\noexpand\csname everysetup#2\endcsname}}

\unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
  {\unexpanded\def#2{\dosetvalue #1}%
   \unexpanded\def#3{\dosetevalue#1}%
   \unexpanded\def#4{\doletvalue #1}%
   \unexpanded\def#5{\doletvalue #1\empty}}%

\startinterface english

    \unexpanded\def\mult_interfaces_install_direct_parameter_set_handler#1#2#3#4#5%
      {\unexpanded\def#2##1{\expandafter \def\csname#1##1\endcsname}%
       \unexpanded\def#3##1{\expandafter\edef\csname#1##1\endcsname}%
       \unexpanded\def#4##1{\expandafter \let\csname#1##1\endcsname}%
       \unexpanded\def#5##1{\expandafter \let\csname#1##1\endcsname\empty}}%

\stopinterface

\unexpanded\def\installdirectparametersethandler#1#2%
  {\normalexpanded
     {\mult_interfaces_install_direct_parameter_set_handler
        {\noexpand#1}% \??aa
        \expandafter\noexpand\csname set#2parameter\endcsname
        \expandafter\noexpand\csname setexpanded#2parameter\endcsname
        \expandafter\noexpand\csname let#2parameter\endcsname
        \expandafter\noexpand\csname reset#2parameter\endcsname}}

\let\installdirectstyleandcolorhandler\installstyleandcolorhandler

\unexpanded\def\installdirectcommandhandler#1#2%
  {\installdirectparameterhandler    {#1}{#2}%
   \installdirectsetuphandler        {#1}{#2}%
   \installdirectparametersethandler {#1}{#2}%
   \installdirectstyleandcolorhandler{#1}{#2}}

\unexpanded\def\installsetuponlycommandhandler#1#2%
  {\installdirectparameterhandler{#1}{#2}%
   \installdirectsetuphandler    {#1}{#2}%
  }% maybe \installdirectparametersethandler {#1}{#2}%

% Experiment:

% \installcorenamespace {one}
% \installcorenamespace {two}
%
% \installcommandhandler \??one {one} \??one
% \installcommandhandler \??two {two} \??two
%
% \defineone[test] \setupone[test][alpha=first]
% \definetwo[test] \setuptwo[test][beta=second]
%
% \protect
%
% \def\currentone{test}
% \def\currenttwo{test}
%
% \relateparameterhandlers {two} {test} {one} {test}
%
% yes:\oneparameter{alpha}\par
% nop:\oneparameter{beta}\par
% yes:\twoparameter{alpha}\par
% yes:\twoparameter{beta}\par

\unexpanded\def\relateparameterhandlers#1#2#3#4% {from} {instance} {to} {instance}
  {\expandafter\edef\csname\csname#1namespace\endcsname#2:\s!parent\endcsname{\csname#3namespace\endcsname#4}}

%D Here is another experiment:

\unexpanded\def\installactionhandler#1%
  {\normalexpanded
     {\mult_interfaces_install_action_handler
        {#1}%
        \expandafter\noexpand\csname current#1\endcsname
        \expandafter\noexpand\csname setupcurrent#1\endcsname
        \expandafter\noexpand\csname #1_action\endcsname}}

\unexpanded\def\mult_interfaces_install_action_handler#1#2#3#4%
  {\unexpanded\expandafter\def\csname#1\endcsname{\dodoubleempty#4}%
   \unexpanded\def#4[##1][##2]%
     {\begingroup
      \ifsecondargument
        \edef#2{##1}%
        #3[##2]%
      \else\iffirstargument
        \doifassignmentelse{##1}
          {\let#2\empty
           #3[##1]}%
          {\edef#2{##1}}%
      \else
        \let#2\empty
      \fi\fi
      \directsetup{handler:action:#1}%
      \endgroup}}

% First we had, in tune with the regular system variables:
%
% \starttyping
% \unexpanded\def\installnamespace#1{\setvalue{????#1}{@@@@#1}}
% \stoptyping
%
% The following variant is nicer and in principle faster but that gets
% unnoticed unless lots of expansion happens. Also, we can use long tags
% but the internal expansion will be relatively small (and unlikely more
% than 4 characters). For instance, \??xx used to expand to @@xx but now
% becomes for instance 123::. This is one character more but in quite some
% cases we had : after such a tag in the old situation. In the new situation
% we create more namespaces and don't need that : any more, so we end up
% with on the average the same amount of tokens and definitely less when
% we consider cases like \??xx:\c!align: which now is just \??somealign and
% therefore has length 5 now (instead of 4+1+5+1=10).
%
% Eventualy we will have a verbose \blablanamespace and the difference between
% core and regular can go ... after all, \xxxparameter can already clash between
% the two prefix groups .. if users use this mechanism a lot they should use
% verbose names anyway (the old two character names were mostly an optimization
% as they also expanded to these characters).

% todo: register namespaces at lua end for logging and reverse resolve
% todo: move this to syst-ini so that we can use it real early

\newcount\c_mult_interfaces_n_of_namespaces

%def\v_interfaces_prefix_template{\number    \c_mult_interfaces_n_of_namespaces>}
\def\v_interfaces_prefix_template{\characters\c_mult_interfaces_n_of_namespaces>}

\def\v_interfaces_prefix_template % consistently %03i>
  {\ifnum\c_mult_interfaces_n_of_namespaces<\plusten00\else\ifnum\c_mult_interfaces_n_of_namespaces<\plushundred0\fi\fi
   \number\c_mult_interfaces_n_of_namespaces>}

\def\v_interfaces_prefix_template % consistently %03i>
  {\number\c_mult_interfaces_n_of_namespaces>}

\unexpanded\def\installnamespace#1% for modules and users
  {\ifcsname ????#1\endcsname
     \writestatus\m!system{duplicate user namespace '#1'}\wait
   \else
     \global\advance\c_mult_interfaces_n_of_namespaces\plusone
     \expandafter\edef\csname ????#1\endcsname{\v_interfaces_prefix_template}%
   \fi}

\unexpanded\def\installcorenamespace#1%
  {\ifcsname ??#1\endcsname
     \writestatus\m!system{duplicate core namespace '#1'}\wait
   \else
     \global\advance\c_mult_interfaces_n_of_namespaces\plusone
     \expandafter\edef\csname ??#1\endcsname{\v_interfaces_prefix_template}%
     \ctxcommand{registernamespace(\number\c_mult_interfaces_n_of_namespaces,"#1")}%
   \fi}

\def\mult_interfaces_get_parameters_error#1#2#3% redefined
  {\ctxcommand{showassignerror("#1","#2","#3",\the\inputlineno)}%
   \waitonfatalerror}

% We install two core namespaces here, as we want nice error messages. Maybe
% we will reserve the first 9.

\installcorenamespace{fontinstanceready}
\installcorenamespace{fontinstancebasic}
\installcorenamespace{fontinstanceclass}

%D The next one is handy for local assignments.

\installcorenamespace{dummy}

\letvalue\??dummy\empty

           \def\dummyparameter      #1{\csname\??dummy\ifcsname\??dummy#1\endcsname#1\fi\endcsname}
           \def\directdummyparameter#1{\csname\??dummy#1\endcsname}
\unexpanded\def\setdummyparameter   #1{\expandafter\def\csname\??dummy#1\endcsname}
\unexpanded\def\letdummyparameter   #1{\expandafter\let\csname\??dummy#1\endcsname}

% \unexpanded\def\getdummyparameters
%   {\mult_interfaces_get_parameters\??dummy}

\unexpanded\def\getdummyparameters[#1%
  {\if\noexpand#1]%
     \expandafter\gobbleoneargument
   \else
     \let\m_mult_interfaces_namespace\??dummy
     \expandafter\mult_interfaces_get_parameters_indeed
   \fi#1}

\mult_interfaces_install_style_and_color_handler
  \directdummyparameter
  \usedummystyleandcolor
  \usedummystyleparameter
  \usedummycolorparameter

% Maybe a \definecorenamespace[name][directparameter,directsetup][parent]
% but we don't gain much. Actually we might just inline all definitions.

% \enabletrackers[interfaces.namespaces,context.flush]
%
% \definenamespace
%   [xy]
%   [type=module,
%    comment=test module,
%    version=1,
%    name=test,
%    style=yes,
%    command=yes,
%    setup=list,
%    set=yes,
%    parent=xy]
%
% \unprotect
% \getparameters
%   [\????xy]
%   [text=]
% \protect
%
% \definetest[one]
%
% \starttext
%
%   “\testparameter{text}”
%
%   \setuptest[text=foo]
%
%   “\testparameter{text}”
%
%   \setuptest[one][text=bar]
%
%   “\testparameter{text}”
%
% \stoptext
%
% This is a user (module) command:

\unexpanded\def\definenamespace
  {\dodoubleargument\mult_interfaces_define_name_space}

\def\mult_interfaces_define_name_space[#1][#2]% namespace settings
  {\ctxlua{interfaces.namespaces.define(\!!bs#1\!!es,\!!bs#2\!!es)}}

\def\listnamespaces
  {\ctxlua{interfaces.namespaces.list()}}

%D Helper:
%D
%D \starttyping
%D \showparentchain{@@am}{left}
%D \stoptyping

\unexpanded\def\showparentchain#1#2%
  {\writestatus\m!system{chain: [ \mult_interfaces_show_parent_chain{#1#2}]}}

\def\mult_interfaces_show_parent_chain#1%
  {#1 => %
   \ifcsname#1:\s!parent\endcsname
      \expandafter\mult_interfaces_show_parent_chain\csname#1:\s!parent\endcsname
   \fi}

%D Another helper (needs to be applied):

\unexpanded\def\doifelsecommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\firstoftwoarguments
   \else
     \expandafter\secondoftwoarguments
   \fi}

\unexpanded\def\doifcommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\firstofoneargument
   \else
     \expandafter\gobbleoneargument
   \fi}

\unexpanded\def\doifnotcommandhandler#1#2% namespace name
  {\ifcsname#1#2:\s!parent\endcsname
     \expandafter\gobbleoneargument
   \else
     \expandafter\firstofoneargument
   \fi}

\let\doifcommandhandlerelse\doifelsecommandhandler

% another set of (fast) helpers (grep for usage):

\def\expandnamespaceparameter#1#2#3% \??xx \getp \c!xx \c!yy
  {\csname#1\ifcsname#1\expandafter\expandafter\expandafter\mult_aux_expand_namespace_parameter#2#3}

\def\mult_aux_expand_namespace_parameter#1#2% \cs \c!yy
  {#1\endcsname#1\else#2\fi\endcsname}

\def\expandnamespacemacro#1#2#3% \??xx \some_edefed_cs \c!yy
  {\csname#1\ifcsname#1#2\endcsname#2\else#3\fi\endcsname}

\def\expandnamespacevalue#1#2% \??xx {...} \c!yy == optimized \expandcheckedcsname
  {\csname#1\ifcsname#1\normalexpanded{\noexpand\syst_helpers_expand_checked_value{#2}}}

\def\syst_helpers_expand_checked_value#1#2%
  {#1\endcsname#1\else#2\fi\endcsname}

%D Conventions:
%D
%D \starttyping
%D \newcount       \c_class_whatever
%D \newconditional \c_class_whatever
%D \newconstant    \c_class_whatever
%D \newdimen       \d_class_whatever
%D \newskip        \s_class_whatever
%D \newmuskip      \s_class_whatever
%D \newbox         \b_class_whatever
%D \newtoks        \t_class_whatever
%D
%D \edef\p_class_whatever{\classparameter\c!whatever}
%D \edef\m_class_whatever{whatever}
%D \stoptyping

\protect
