// Utility for fetching a nested value from a typography config.
@function _at-get-type-value($config, $level, $name) {
  @return map-get(map-get($config, $level), $name);
}

// Gets the font size for a level inside a typography config.
@function at-font-size($config, $level) {
  @return _at-get-type-value($config, $level, font-size);
}

// Gets the line height for a level inside a typography config.
@function at-line-height($config, $level) {
  @return _at-get-type-value($config, $level, line-height);
}

// Gets the font weight for a level inside a typography config.
@function at-font-weight($config, $level) {
  @return _at-get-type-value($config, $level, font-weight);
}

// Gets the font-family from a typography config and removes the quotes around it.
@function at-font-family($config, $level: null) {
  $font-family: map-get($config, font-family);

  @if $level != null {
    $font-family: _at-get-type-value($config, $level, font-family);
  }

  @return unquote($font-family);
}

// Represents a typography level from the Material design spec.
@function at-typography-level($font-size, $line-height: $font-size, $font-weight: 400) {
  @return (
          font-size: $font-size,
          line-height: $line-height,
          font-weight: $font-weight
  );
}

@function rem($multiplier) {
  $font-size: 10px;
  @return $multiplier * $font-size;
}

// Gets a color from a theme palette (the output of mat-palette).
// The hue can be one of the standard values (500, A400, etc.), one of the three preconfigured
// hues (default, lighter, darker), or any of the aforementioned prefixed with "-contrast".
//
// @param $color-map The theme palette (output of mat-palette).
// @param $hue The hue from the palette to use. If this is a value between 0 and 1, it will
//     be treated as opacity.
// @param $opacity The alpha channel value for the color.
@function mat-color($palette, $hue: default, $opacity: null) {
  // If hueKey is a number between zero and one, then it actually contains an
  // opacity value, so recall this function with the default hue and that given opacity.
  @if type-of($hue) == number and $hue >= 0 and $hue <= 1 {
    @return mat-color($palette, default, $hue);
  }

  $color: map-get($palette, $hue);
  $opacity: if($opacity == null, opacity($color), $opacity);

  @return rgba($color, $opacity);
}

// Applies the correct css rules to an element to give it the elevation specified by $zValue.
// The $zValue must be between 0 and 24.
@mixin mat-elevation($zValue) {
  @if type-of($zValue) != number or not unitless($zValue) {
    @error '$zValue must be a unitless number';
  }
  @if $zValue < 0 or $zValue > 24 {
    @error '$zValue must be between 0 and 24';
  }

  #{$mat-elevation-property}: #{map-get($_umbra-elevation-map, $zValue)},
  #{map-get($_penumbra-elevation-map, $zValue)},
  #{map-get($_ambient-elevation-map, $zValue)};
}

// Returns a string that can be used as the value for a transition property for elevation.
// Calling this function directly is useful in situations where a component needs to transition
// more than one property.
//
// .foo {
//   transition: mat-elevation-transition-property-value(), opacity 100ms ease;
//   will-change: $mat-elevation-property, opacity;
// }
@function mat-elevation-transition-property-value(
  $duration: $mat-elevation-transition-duration,
  $easing: $mat-elevation-transition-timing-function) {
  @return #{$mat-elevation-property} #{$duration} #{$easing};
}

// Applies the correct css rules needed to have an element transition between elevations.
// This mixin should be applied to elements whose elevation values will change depending on their
// context (e.g. when active or disabled).
//
// NOTE(traviskaufman): Both this mixin and the above function use default parameters so they can
// be used in the same way by clients.
@mixin mat-elevation-transition(
  $duration: $mat-elevation-transition-duration,
  $easing: $mat-elevation-transition-timing-function) {
  transition: mat-elevation-transition-property-value($duration, $easing);
  will-change: $mat-elevation-property;
}

// mixin definition ; sets LTR and RTL within the same style call
// @see https://css-tricks.com/almanac/properties/d/direction/
@mixin rtl($prop, $value, $rtl-value) {
  #{$prop}: $value;

  html[dir=rtl] & {
    #{$prop}: $rtl-value;
    unicode-bidi: embed;
  }
  body[dir=rtl] & {
    #{$prop}: $rtl-value;
    unicode-bidi: embed;
  }
  [dir=rtl] & {
    #{$prop}: $rtl-value;
    unicode-bidi: embed;
  }

  bdo[dir=rtl] {
    direction: rtl;
    unicode-bidi: bidi-override;
  }
  bdo[dir=ltr] {
    direction: ltr;
    unicode-bidi: bidi-override;
  }

}
