@use 'sass:meta';
@use 'sass:map';
@use 'sass:list';
@use 'type';
@use 'throw';

// Internal Functions
// ------------------
/// These functions are defined internally,
/// and can be called by name without first being captured
/// using the Sass `get-function()` approach.
/// User should not make changes to this map.
///
/// @access private
/// @group function-register
/// @type map
$internal: ();

// Registration
// ------------
/// This function provides the shared logic used by
/// `function.register()` (for user registration)
/// and `function.internal()` (for internal use).
///
/// @access private
/// @group function-register
///
/// @param {map} $source -
///   The original map source in which to register a function
/// @param {function} $function -
///   The function to be registered
/// @param {string | arglist} $names... -
///   One or more alias names (strings)
///   to use for map-access to the function
/// @return {map} -
///   Updated registration map
/// @throws `$function` is not available to register with Accoutrement
@function set($source, $function, $names...) {
  $origin: 'function-register';

  @if not type.check($function, 'function') {
    @return type.error($function, 'function', $origin, '$function');
  }

  @if (list.length($names) == 0) {
    $error: 'Provide at least one name for this function';

    @return throw.error($error, $origin);
  }

  // register captured functions
  @each $name in $names {
    @if map.has-key($source, $name) {
      $error: 'A function has already been registered under the name `#{$name}`';

      @return throw.error($error, $origin);
    }

    $source: map.merge(
      $source,
      (
        $name: $function,
      )
    );
  }

  @return $source;
}

// Internal [mixin]
// ----------------
/// Register internal functions.
///
/// @access private
/// @group function-register
/// @param {function} $function -
///   The function to be registered
/// @param {string | arglist} $names... -
///   One or more alias names (strings)
///   to use for map-access to the function
@mixin internal($function, $names...) {
  $internal: set($internal, $function, $names...) !global;
}
