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

$_prefix: 'acms-';

// Utility generator
// Used to generate utilities & print utilities
@mixin generate-utility($utility, $infix: '') {
  $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' {
    // A single value is converted to a map with a null key.
    @if list.length($values) == 1 {
      $values: (
        null: list.nth($values, 1),
      );
    } @else {
      $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);

    // Use custom CSS variable name if present, otherwise default to `class`
    $css-variable-name: if(
      map.has-key($utility, css-variable-name),
      map.get($utility, css-variable-name),
      map.get($utility, class)
    );

    // State params to generate pseudo-classes
    $state: if(map.has-key($utility, state), map.get($utility, state), ());
    $infix: if($property-class == '' and string.slice($infix, 1, 1) == '-', string.slice($infix, 2), $infix);

    // Don't prefix if value key is null (e.g. with shadow class)
    $property-class-modifier: if($key, if($property-class == '' and $infix == '', '', '-') + $key, '');
    $is-css-var: map.get($utility, css-var);
    $is-local-vars: map.get($utility, local-vars);

    @if $value {
      @if $is-css-var {
        .#{$_prefix + $property-class + $infix + $property-class-modifier} {
          --#{$_prefix}#{$css-variable-name}: #{$value};
        }

        @each $pseudo in $state {
          .#{$_prefix + $property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
            --#{$_prefix}#{$css-variable-name}: #{$value};
          }
        }
      } @else {
        .#{$_prefix + $property-class + $infix + $property-class-modifier} {
          @each $property in $properties {
            @if $is-local-vars {
              @each $local-var, $variable in $is-local-vars {
                --#{$_prefix}#{$local-var}: #{$variable};
              }
            }

            #{$property}: $value !important;
          }
        }

        @each $pseudo in $state {
          .#{$_prefix + $property-class + $infix + $property-class-modifier}-#{$pseudo}:#{$pseudo} {
            @each $property in $properties {
              @if $is-local-vars {
                @each $local-var, $variable in $is-local-vars {
                  --#{$_prefix}#{$local-var}: #{$variable};
                }
              }

              #{$property}: $value !important;
            }
          }
        }
      }
    }
  }
}
