@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '../functions' as functions;
@use '../variables' as variables;
@use '../utilities' as utilities;
@use './breakpoints-mixins' as breakpoints-mixins;
// Utility generator
// Used to generate utilities & print utilities
@mixin generate-utility($utility, $infix, $enable-important-utilities: variables.$enable-important-utilities) {
  $values: map.get($utility, values);

  // If the values are a list or string, convert it into a map
  @if meta.type-of($values) == 'string' or meta.type-of(list.nth($values, 1)) != 'list' {
    $values: list.zip($values, $values);
  }

  @each $key, $value in $values {
    $properties: map.get($utility, property);

    // Multiple properties are possible, for example with vertical or horizontal margins or paddings
    @if meta.type-of($properties) == 'string' {
      $properties: list.append((), $properties);
    }

    // Use custom class if present
    $property-class: if(map.has-key($utility, class), map.get($utility, class), list.nth($properties, 1));
    $property-class: if($property-class == null, '', $property-class);

    $infix: if($property-class == '' and string.slice($infix, 1, 1) == '-', string.slice($infix, 2), $infix);

    // Don't prefix if value key is null (eg. with shadow class)
    $property-class-modifier: if($key, if($property-class == '' and $infix == '', '', '-') + $key, '');

    @if $value != null {
      .#{$property-class + $infix + $property-class-modifier} {
        @each $property in $properties {
          #{$property}: $value if($enable-important-utilities or map.has-key($utility, important), !important, null);
        }
      }
    }
  }
}

// Generate a set of utilities
// Defaults to generating ALL utilities in _utilities.scss

@mixin generate-utilities(
  $utilities: utilities.$utilities,
  $enable-important-utilities: variables.$enable-important-utilities
) {
  // Loop over each breakpoint

  @each $breakpoint in map.keys(variables.$grid-breakpoints) {
    // Generate media query if needed

    @include breakpoints-mixins.media-breakpoint-up($breakpoint) {
      $infix: functions.breakpoint-infix($breakpoint, variables.$grid-breakpoints);

      // Loop over each utility property

      @each $key, $utility in $utilities {
        // The utility can be disabled with `false`, thus check if the utility is a map first
        // Only proceed if responsive media queries are enabled or if it's the base media query

        @if meta.type-of($utility) == 'map' and (map.get($utility, responsive) or $infix == '') {
          @include generate-utility($utility, $infix, $enable-important-utilities);
        }
      }
    }
  }

  // Print utilities

  @media print {
    @each $key, $utility in $utilities {
      // The utility can be disabled with `false`, thus check if the utility is a map first
      // Then check if the utility needs print styles

      @if meta.type-of($utility) == 'map' and map.get($utility, print) == true {
        @include generate-utility($utility, '-print', true);
      }
    }
  }
}
