// Base API
// ========


// Size [function]
// ---------------
/// Access a named size in your `$sizes` map,
/// using any comparable units.
///
/// @group sizes
///
/// @param {String | Length | List} $size -
///   The name of a size in your configuration (e.g. `line-height`),
///   or a length to be converted into different units (e.g. `24px`),
///   or a base-size and adjustments to be made
///   (e.g. `24px ('minor-third': 2)`).
///   For the sake of consistent documentation,
///   I recommend keeping adjustments in the configuration
///   whenever possible.
/// @param {String} $unit [null] -
///   The desired units for the output (e.g. `px` or `rem`).
/// @throw -
///   The calculated value is not a valid CSS length.
/// @return {Length} -
///   The calculated length, in the requested units.
@function size(
  $size,
  $unit: null
) {
  // Parse arguments
  $size: map-get($sizes, $size) or $size;
  $base: nth($size, 1);
  $adjust: if(length($size) > 1, nth($size, 2), ());

  // Recursive check
  $size: if(map-has-key($sizes, $base), size($base, false), $base);

  // Adjustments
  @each $key, $value in $adjust {
    $size: _ac-scale-adjust-size($size, $key, $value);
  }

  // Validation
  @if type-of($size) != 'number' {
    @error '#{$size} is not a valid length for CSS.';
  }

  // Units
  @if $unit {
    $size: convert-units($size, $unit);
  }

  // Return
  @return $size;
}


// Negative [function]
// -------------------
/// Return the negative value of any length,
/// in comparable units.
///
/// @group sizes
///
/// @param {String | Length | List} $size -
///   The name of a size in your configuration (e.g. `line-height`),
///   or a length to be converted into different units (e.g. `24px`),
///   or a base-size and adjustments to be made
///   (e.g. `24px ('minor-third': 2)`).
///   For the sake of consistent documentation,
///   I recommend keeping adjustments in the configuration
///   whenever possible.
/// @param {String} $unit [null] -
///   The desired units for the output (e.g. `px` or `rem`).
/// @return {Length} -
///   The calculated negative length, in the requested units.
@function negative(
  $size,
  $unit: null
) {
  @return 0 - size($size, $unit);
}


// Square [mixin]
// --------------
/// Create a square by setting equal CSS `height` and `width` properties
/// with the given size & unit value.
///
/// @group sizes
///
/// @param {String | Length | List} $size -
///   The name of a size in your configuration (e.g. `line-height`),
///   or a length to be converted into different units (e.g. `24px`),
///   or a base-size and adjustments to be made
///   (e.g. `24px ('minor-third': 2)`).
///   For the sake of consistent documentation,
///   I recommend keeping adjustments in the configuration
///   whenever possible.
/// @param {String} $unit [null] -
///   The desired units for the output (e.g. `px` or `rem`).
/// @output -
///   Equal CSS height and width properties,
///   set to the given size and units.
@mixin square(
  $size,
  $unit: null
) {
  $size: size($size, $unit);

  height: $size;
  width: $size;
}



// Adjust Size
// ===========
/// Calculate ratio, linear, or arbitrary adjustments
/// to a base size.
///
/// @access private
///
/// @param {Number} $size -
///   The original size to perform adjusments on
/// @param {String | Number} $key -
///   The adjustment to perform,
///   given as either a numeric ratio,
///   named ratio keyword,
///   or function name to call.
/// @param {Any} $value -
///   Any required adjustment arguments,
///   such as the number of times to apply a ratio,
///   or additional arguments to be passed to a function.
/// @return {Number} -
///   Results of the adjustment.
@function _ac-scale-adjust-size(
  $size,
  $key,
  $value
) {
  $ratio: _get-ratio($key);

  @if $ratio == 'linear' {
    @return $size * $value;
  } @else if (type-of($ratio) == 'number') {
    $multiplier: _accoutrement-pow($ratio, $value);
    @return $size * $multiplier;
  } @else if (type-of($key) == 'function') or function-exists($key) {
    $function: _ac-scale-get-function($key);
    @return call($function, $size, $value...);
  }

  @error '#{$key} is not a valid ratio or function for adusting sizes.';
}


