
\DeclareObjectType { name }
  {
    first  : tokenlist                   ,
    middle : tokenlist                   ,
    last   : tokenlist                   ,
    first  : .required                   ,
    last   : .required                   ,
  }

\DeclareTemplateInterface { name } { full }
  {
    reversed           : boolean = false ,
    use-first-name     : boolean = true  ,
    use-middle-name    : boolean = true  ,
    use-last-name      : boolean = true  ,
    first-name-format  : tokenlist       ,
    middle-name-format : tokenlist       ,
    last-name-format   : tokenlist       ,
  }

\tl_new:N \l_names_first_name_tl
\tl_new:N \l_names_middle_name_tl
\tl_new:N \l_names_last_name_tl

\tl_new:N \l_names_first_format_tl
\tl_new:N \l_names_middle_format_tl
\tl_new:N \l_names_last_format_tl

\bool_new:N \l_names_use_first_bool
\bool_new:N \l_names_use_middle_bool
\bool_new:N \l_names_use_last_bool

\bool_new:N \l_names_reversed_bool

\DeclareTemplateCode { name } { full }
  {
    first              = \l_names_first_name_tl    ,
    middle             = \l_names_middle_name_tl   ,
    last               = \l_names_last_name_tl     ,
  }
  {
    reversed           = \l_names_reversed_bool    ,
    use-first-name     = \l_names_use_first_bool   ,
    use-middle-name    = \l_names_use_middle_bool  ,
    use-last-name      = \l_names_use_last_bool    ,
    first-name-format  = \l_names_first_format_tl  ,
    middle-name-format = \l_names_middle_format_tl ,
    last-name-format   = \l_names_last_format_tl   ,
  }
  {
    \AssignTemplateKeys
    
    \bool_if:nT
    {
      \tl_empty_p:N \l_names_middle_name_tl &&
      \l_names_use_middle_bool
    }
    {
      \typeout{! This is an error and I'm far too lazy to create a    ^^J
                 proper l3msg.  (In practice, probably better to be   ^^J
                 a warning.)  We were provided no middle name to use  ^^J
                 with the use-middle-name directive.}
    }
    
    \bool_if:NTF \l_names_reversed_bool
    {
      \bool_if:NT \l_names_use_last_bool
      {{\tl_use:N \l_names_last_format_tl \l_names_last_name_tl}}
      \bool_if:nT
      {
        \l_names_use_first_bool &&
        \l_names_use_last_bool
      }
      { , ~ }
      \bool_if:NT \l_names_use_first_bool
      {{\tl_use:N \l_names_first_format_tl \l_names_first_name_tl}}
      \bool_if:NT \l_names_use_middle_bool
      {
        \bool_if:NT \l_names_use_first_bool
        { ~ }
        {\tl_use:N \l_names_middle_format_tl \l_names_middle_name_tl}
      }
    }
    {
      \bool_if:NT \l_names_use_first_bool
      {
        {\tl_use:N \l_names_first_format_tl \l_names_first_name_tl}
        \bool_if:nT
        {
          \l_names_use_middle_bool ||
          \l_names_use_last_bool
        }
        { ~ }
      }
      
      \bool_if:NT \l_names_use_middle_bool
      {
        {\tl_use:N \l_names_middle_format_tl \l_names_middle_name_tl}
        \bool_if:NT \l_names_use_last_bool
        { ~ }
      }
      \bool_if:NT \l_names_use_last_bool
      {
        {\tl_use:N \l_names_last_format_tl \l_names_last_name_tl}
      }
    }
  }

\DeclareInstance { name } { standard } { full } { }

\DeclareDocumentCommand \Name { >{\SplitArgument{1}{~}}m }
  {
    \UseInstance { name } { standard }
      {
        first = \use_i:nn  #2,
        last  = \use_ii:nn #2,
      }
  }

\DeclareDocumentCommand \SpecialName { m m m m }
  {
    \UseTemplate { name } { full } { #1 }
      {
        first  = #2,
        last   = #3,
        middle = #4,
      }
  }
