@use 'sass:color';
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';

/// Include content under the current selector (&) or the document root if there is no current
/// selector.
/// @param {String} $root [html] The default root selector to use when there is no current selector.
/// @output The given content under the current selector, or root selector if there is no current
///     selector.
/// @content Content to output under the current selector, or root selector if there is no current
///     selector.
@mixin current-selector-or-root($root: html) {
  @if & {
    @content;
  }
  @else {
    #{$root} {
      @content;
    }
  }
}

/// A version of the standard `map.merge` function that takes a variable number of arguments.
/// Each argument is merged into the final result from left to right.
/// @param {List} $maps The maps to combine with map.merge
/// @return {Map} The combined result of successively calling map.merge with each parameter.
@function merge-all($maps...) {
  $result: ();
  @each $map in $maps {
    $result: map.merge($result, $map);
  }
  @return $result;
}

/// A version of the standard `map.deep-merge` function that takes a variable number of arguments.
/// Each argument is deep-merged into the final result from left to right.
/// @param {List} $maps The maps to combine with map.deep-merge
/// @return {Map} The combined result of successively calling map.deep-merge with each parameter.
@function deep-merge-all($maps...) {
  $result: ();
  @each $map in $maps {
    $result: map.deep-merge($result, $map);
  }
  @return $result;
}

/// Coerces the given value to a list, by converting any non-list value into a single-item list.
/// This should be used when dealing with user-passed lists of args to avoid confusing errors,
/// since Sass treats `($x)` as equivalent to `$x`.
/// @param {Any} $value The value to coerce to a list.
/// @return {List} The original $value if it was a list, otherwise a single-item list containing
///     $value.
@function coerce-to-list($value) {
  @return if(meta.type-of($value) != 'list', ($value,), $value);
}

/// A version of the Sass `color.change` function that is safe ot use with CSS variables.
@function safe-color-change($color, $args...) {
  $args: meta.keywords($args);
  @return if(meta.type-of($color) == 'color', color.change($color, $args...), $color);
}

/// Gets the given arguments as a map of keywords and validates that only supported arguments were
/// passed.
/// @param {ArgList} $args The arguments to convert to a keywords map.
/// @param {List} $supported-args The supported argument names.
/// @return {Map} The $args as a map of argument name to argument value.
@function validate-keyword-args($args, $supported-args) {
  @if list.length($args) > 0 {
    @error #{'Expected keyword args, but got positional args: '}#{$args};
  }
  $kwargs: meta.keywords($args);
  @each $arg, $v in $kwargs {
    @if list.index($supported-args, $arg) == null {
      @error #{'Unsupported argument '}#{$arg}#{'. Valid arguments are: '}#{$supported-args};
    }
  }
  @return $kwargs;
}
