// Emits config metadata if it has not already been emitted.
@mixin _anthology-emit-metadata()
{
  @if not $_anthology-metadata-is-emitted
  {
    @at-root -anthology-metadata::before {
      content: A(to-json, ( 'config': _A(config-to-map) ));
    }

    $_anthology-metadata-is-emitted: true !global;
  }
}

// Performs the actual CSS generation for all combinations of selectors with a given `$shorthand` and `$adjective`.
@mixin _anthology-do-emit($shorthand, $adjective, $property, $value, $breakpoint, $pseudos, $themes, $important, $silent)
{
  $full-selector-args: ($shorthand, $adjective, $property, $value, $breakpoint, $pseudos, $themes, $important, $silent);

  @if $important
  {
    $full-selector: _A(full-selector, $full-selector-args...);

    #{$full-selector} {
      #{$property}: $value !important;
    }
  }

  @else
  {
    $full-selector: _A(full-selector, $full-selector-args...);

    #{$full-selector} {
      #{$property}: $value;
    }
  }
}

/// Emits non-responsive rules. Emitted properties are flushed afterwards.
///
/// @param {Bool} $important - Whether to emit '!important' versions of the rules [default: false].
@mixin anthology-emit($options: ())
{
  // Ensure `A(configure, ...)` has been included prior.
  @if not $_anthology-config-is-ready {
    @error '[anthology::emit] --- Before emitting, call `@include A(configure...);` and define some functional properties with `A(define, ...)`.';
  }

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

  // Unpack options
  $important: A(map-get, $options, 'important');
  $silent: A(map-get, $options, 'silent');
  $flush-cache: A(map-get, $options, 'flush-cache');

  // Emit metadata
  @include _A(emit-metadata);

  @if length(A(map-get, $_anthology-define-state, 'generic')) == 0
  {
    @warn '[anthology::emit] --- Nothing to emit';
  }

  $_anthology-extend-silent-generic: $silent !global;

  @each $shorthand, $adjectives in A(map-get, $_anthology-define-state, 'generic')
  {
    @each $adjective, $helper in $adjectives
    {
      // Unpack helper
      $property: nth($helper, 1);
      $value: nth($helper, 2);
      $important-override: nth($helper, 3);
      $pseudos: nth($helper, 4);
      $themes: nth($helper, 5);

      $should-emit-important: $important and $important-override;

      @include _A(do-emit,
        $shorthand: $shorthand,
        $adjective: $adjective,
        $property: $property,
        $value: $value,
        $breakpoint: null,
        $pseudos: $pseudos,
        $themes: $themes,
        $important: false,
        $silent: $silent,
      );

      @if $should-emit-important
      {
        @include _A(do-emit,
          $shorthand: $shorthand,
          $adjective: $adjective,
          $property: $property,
          $value: $value,
          $breakpoint: null,
          $pseudos: $pseudos,
          $themes: $themes,
          $important: true,
          $silent: $silent,
        );
      }
    }
  }

  $new-emit-state: A(map-merge, A(map-get, $_anthology-emit-state, 'generic'), A(map-get, $_anthology-define-state, 'generic'));
  $_anthology-emit-state: A(map-set, $_anthology-emit-state, 'generic', $new-emit-state) !global;
  @if $flush-cache
  {
    $_anthology-define-state: _A(flush-define-state, 'generic') !global;
  }

  // Disallow configuration after emitting.
  $_anthology-should-block-config: true !global;
}

/// Emits responsive, media query efficient helpers. Emitted properties are flushed afterwards.
///
/// @param {Bool} $important - Whether to emit '!important' versions of the rules [default: false].
@mixin anthology-emit-responsive($options: ())
{
  // Ensure `A(configure, ...)` has been included prior.
  @if not $_anthology-config-is-ready {
    @error '[anthology::emit-responsive] --- Before emitting, call `@include A(configure...);` and define some functional properties with `A(define, ...)`.';
  }

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

  // Unpack options
  $important: A(map-get, $options, 'important');
  $silent: A(map-get, $options, 'silent');
  $flush-cache: A(map-get, $options, 'flush-cache');

  @include _A(emit-metadata);

  @if not $_anthology-config-breakpoints
  {
    @warn '[anthology::emit-responsive] --- Responsive breakpoints are not configured. Make sure to call `@include A(configure, ( 'breakpoints': (...) ) );`';
  }

  $_anthology-extend-silent-responsive: $silent !global;

  @each $breakpoint, $shorthands in A(map-get, $_anthology-define-state, 'responsive')
  {
    @include A(breakpoint, $breakpoint)
    {
      @each $shorthand, $adjectives in $shorthands
      {
        @each $adjective, $attributes in $adjectives
        {
          // Unpack attributes
          $property: nth($attributes, 1);
          $value: nth($attributes, 2);
          $important-override: nth($attributes, 3);
          $include-responsive-tag: nth($attributes, 4);
          $pseudos: nth($attributes, 5);
          $themes: nth($attributes, 6);

          $should-emit-breakpoint-tag: if($include-responsive-tag, $breakpoint, null);
          $should-emit-important: $important and $important-override;

          @include _A(do-emit,
            $shorthand: $shorthand,
            $adjective: $adjective,
            $property: $property,
            $value: $value,
            $breakpoint: $should-emit-breakpoint-tag,
            $pseudos: $pseudos,
            $themes: $themes,
            $important: false,
            $silent: $silent,
          );

          @if $should-emit-important
          {
            @include _A(do-emit,
              $shorthand: $shorthand,
              $adjective: $adjective,
              $property: $property,
              $value: $value,
              $breakpoint: $should-emit-breakpoint-tag,
              $pseudos: $pseudos,
              $themes: $themes,
              $important: true,
              $silent: $silent,
            );
          }
        }
      }
    }
  }

  $new-emit-state: A(map-merge, A(map-get, $_anthology-emit-state, 'responsive'), A(map-get, $_anthology-define-state, 'responsive'));
  $_anthology-emit-state: A(map-set, $_anthology-emit-state, 'responsive', $new-emit-state) !global;
  @if $flush-cache
  {
    $_anthology-define-state: _A(flush-define-state, 'responsive') !global;
  }

  // Disallow configuration after emitting.
  $_anthology-should-block-config: true !global;
}
