@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
// Note that this file is called `private`, because the APIs in it aren't public yet.
// Once they're made available, the code should be moved out into an `index.scss`.

// Taken from mat-density with small modifications to not rely on the new Sass module
// system, and to support arbitrary properties in a density configuration.
// https://github.com/material-components/material-components-web/blob/master/packages/mdc-density

$_density-interval: 4px !default;
$_minimum-scale: minimum !default;
$_maximum-scale: maximum !default;
$_supported-scales: (default, $_minimum-scale, $_maximum-scale) !default;
$_default-scale: 0 !default;

// Whether density should be generated at root. This will be temporarily set to `true`
// whenever density styles for legacy themes are generated.
$private-density-generate-at-root: false;
// Whether density styles should be generated. This will be temporarily set to `false` if
// duplicate density styles for a legacy theme would be generated. For legacy themes,
// we always generate the default density **only once** at root.
$private-density-generate-styles: true;

// Mixin that can be used to wrap density styles of given components. The mixin will
// move the density styles to root if the `$mat-private-density-generate-at-root` global variable
// is set. If `$mat-private-density-generate-styles` is set to `false`, generation of density
// styles wrapped in this mixin is skipped. This mixin exists to improve backwards compatibility
// of the new theming API where density styles are included as part of themes. Previously,
// density styles of components were part of their base styles. With the new API, they are
// part of the theming system. The `<..>-theme` mixins generate density by default unless
// the density configuration is explicitly specified as per new API. This means, that projects
// using `<..>-theme` mixins for separate themes (like `.dark-theme`) will cause duplicate
// density styles. This is breaking as it increases specificity of density styles. This mixin
// provides an API to control generation of density styles so that we can ensure they are only
// created *once* and at root.
@mixin private-density-legacy-compatibility() {
  @if $private-density-generate-styles and $private-density-generate-at-root {
    @at-root {
      @content;
    }
  }
  @else if $private-density-generate-styles {
    @content;
  }
}

@function private-density-prop-value($density-config, $density-scale, $property-name) {
  @if (meta.type-of($density-scale) == 'string' and
      list.index($list: $_supported-scales, $value: $density-scale) == null) {
    @error 'mat-density: Supported density scales #{$_supported-scales}, '  +
      'but received #{$density-scale}.';
  }

  $value: null;
  $property-scale-map: map.get($density-config, $property-name);

  @if map.has-key($property-scale-map, $density-scale) {
    $value: map.get($property-scale-map, $density-scale);
  }
  @else {
    $value: map.get($property-scale-map, default) + $density-scale * $_density-interval;
  }

  $min-value: map.get($property-scale-map, $_minimum-scale);
  $max-value: map.get($property-scale-map, $_maximum-scale);

  @if ($value < $min-value or $value > $max-value) {
    @error 'mat-density: #{$property-name} must be between #{$min-value} and ' +
      '#{$max-value} (inclusive), but received #{$value}.';
  }

  @return $value;
}
