/// Defines a functional CSS rule. For optimization reasons, this mixin does not emit any CSS. To emit currently defined
/// helpers, use 'A(emit, ...)' and 'A(emit-responsive, ...)'.
///
/// @param {String} $shorthand - The name for this series of helpers.
/// @param {String} $property - The CSS property to target.
/// @param {Map} $values - A map of values to assign.
/// @param {Bool} $options.important - Whether to emit '!important' versions of the rules. This overrides the argument
/// in `A(emit, ...)` and `A(emit-responsive, ...)` [default: true].
/// @param {Bool} $options.responsive - Whether to emit responsive versions of the rules. This overrides the argument in
/// `A(emit, ...)` and `A(emit-responsive, ...)` [default: true].
/// @param {List} $options.pseudos - A list of pseudo-classes or pseudo-elements to generate selectors for.
/// @param {List} $options.themes - A list of themes to generate selectors for.
@mixin anthology-define($shorthand, $property, $values, $options: ())
{
  // Ensure `A(configure, ...)` has been included prior.
  @if not $_anthology-config-is-ready {
    @error '[anthology::define] --- Before defining your own functional properties, call `@include A(configure...);`.';
  }

  // Merge default options
  $options: _A(define-options, $options);

  // Unpack options
  $important: A(map-get, $options, 'important');
  $responsive: A(map-get, $options, 'responsive');
  $pseudos: A(map-get, $options, 'pseudos');
  $themes: A(map-get, $options, 'themes');

  // Visit each adjective and cache its configuration.
  @each $adjective, $value in $values
  {
    // Map explicitly responsive properties.
    @if type-of($value) == map
    {
      @each $breakpoint, $breakpoint-value in $value
      {

        // Handle valid breakpoints.
        @if A(map-has-key, $_anthology-define-state, ('responsive', $breakpoint))
        {
          @if $responsive == true
          {
            $_anthology-define-state: A(map-set,
              $_anthology-define-state,
              ('responsive', $breakpoint, $shorthand, $adjective),
              ($property, $breakpoint-value, $important, false, $pseudos, $themes)
            ) !global;
          }
        }

        // Handle the default case.
        @else if $breakpoint == 'default'
        {
          $_anthology-define-state: A(map-set,
            $_anthology-define-state,
            ('generic', $shorthand, $adjective),
            ($property, $breakpoint-value, $important, $pseudos, $themes)
          ) !global;
        }

        // Throw if breakpoint key is invalid.
        @else
        {
          @error "[anthology::define] --- Invalid breakpoint key: #{$breakpoint}. Choose one of: #{map-keys(A(map-get, $_anthology-define-state, 'responsive'))}, or default.";
        }

      }
    }

    // Add default properties
    @else
    {

      @if $responsive == true
      {
        // Map responsive properties dynamically
        @each $breakpoint in map-keys(A(map-get, $_anthology-define-state, 'responsive'))
        {
          $_anthology-define-state: A(map-set,
            $_anthology-define-state,
            ('responsive', $breakpoint, $shorthand, $adjective),
            ($property, $value, $important, true, $pseudos, $themes)
          ) !global;
        }
      }

      $_anthology-define-state: A(map-set,
        $_anthology-define-state,
        ('generic', $shorthand, $adjective),
        ($property, $value, $important, $pseudos, $themes)
      ) !global;

    }

  }
}
