////
/// @group theme
////

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

@import '@react-md/utils/dist/scss/functions';
@import './color-palette';
@import './helpers';
@import './variables';

/// A theme utility function to convert a material design color to the same
/// color but with a different swatch. If your app is not using material design
/// colors, this utility function is useless but you will need to define
/// fallback colors so compilation does not fail.
///
/// @example scss - Example Material Design Color Usage
///   .something {
///     color: rmd-theme-get-swatch($rmd-theme-primary, 200);
///   }
///
///   .something-2 {
///     color: rmd-theme-get-swatch($rmd-theme-primary, 200, true);
///   }
///
/// @example scss - Example Non-Material Design Color Usage
///   $my-theme-color: #3498db;
///   // START_NO_COMPILE
///   .something-failed {
///     color: rmd-theme-get-swatch($my-theme-color, 200);
///   }
///   // END_NO_COMPILE
///
///   .something-failed--fixed {
///     color: rmd-theme-get-swatch($my-theme-color, 200, false, rgba($my-theme-color, .32));
///   }
///
/// @param {Color} color - The material design color to create a new color for
/// with the provided swatch.
/// @param {Number} swatch - The swatch to apply. This should be one of
/// `$rmd-theme-primary-suffixes` or `$rmd-theme-accent-suffixes` if the
/// `$accent` param is enabled.
/// @param {Boolean} accent [false] - Boolean if the swatch is an accent color
/// instead of a primary color.
/// @param {Color} fallback-color [null] - The color to fallback to if the
/// `$color` is not a valid material design color. Since this is null by
/// default, the compilation will fail until a valid fallback is provided.
/// @param {String} fallback-name [null] - The name of a variable or global
/// variable that should be set to automatically fix the compilation error.
/// @return {Color} the new color within the same color family with the provided
/// swatch and optional accent.
@function rmd-theme-get-swatch(
  $color,
  $swatch,
  $accent: false,
  $fallback-color: null,
  $fallback-name: null
) {
  $current-color-index: list.index(map.values($rmd-theme-color-map), $color);

  @if not $current-color-index or $current-color-index < 1 {
    @if $fallback-color == null {
      $fallback: if(
        $fallback-name,
        "the '$#{$fallback-name}' variable",
        'a fallback color'
      );

      $error-msg: "Invalid material design color: '#{$color}'. If this was intentional because your app does " +
        'not use material design colors, set #{$fallback} instead to get a correct color for the provided swatch: ' +
        '#{$swatch}.';
      @error $error-msg;
    } @else if type-of($fallback-color) != 'color' {
      @error "Invalid fallback color: '#{$fallback-color}'. This must be a valid color.";
    }

    @return $fallback-color;
  }

  $suffixes: rmd-utils-validate(
    if($accent, $rmd-theme-accent-suffixes, $rmd-theme-primary-suffixes),
    $swatch,
    'material design color swatch'
  );

  $current-color-name: list.nth(
    map.keys($rmd-theme-color-map),
    $current-color-index
  );
  $accent-index: string.index($current-color-name, '-a-');
  @if $accent-index {
    $current-color-name: string.slice(
      $current-color-name,
      1,
      $accent-index - 1
    );
  } @else {
    $index: 1;
    $found: false;
    @while not $found and $index < length($rmd-theme-colors) {
      $suffix: list.nth($rmd-theme-colors, $index);
      $suffix-index: string.index($current-color-name, $suffix);
      @if $suffix-index {
        $found: true;
        $current-color-name: string.slice(
          $current-color-name,
          1,
          $suffix-index - 1 + string.length($suffix)
        );
      }

      $index: $index + 1;
    }
  }

  $color-name: '#{$current-color-name}#{if($accent, '-a', '')}-#{$swatch}';

  @return map-get($rmd-theme-color-map, $color-name);
}

/// A small utility function to get a color from the current theme. This is
/// normally used along with the `rmd-theme-var` function so that both css
/// variables and a fallback can be applied. If the provided style prop is a
/// color or 'currentColor', the provided style prop will be returned instead.
///
/// You are _most_ likely looking for the `rmd-theme` mixin and not the
/// functions instead.
///
/// @param {String} theme-name - The theme style to get. This should be one of
/// the keys from `$rmd-theme-values`.
/// @return {Color} the theme color.
@function rmd-theme($theme-name) {
  @return rmd-theme-get-var-value($theme-name, $rmd-theme-values, theme);
}

/// A small utility function to get a color from the current theme as a css
/// variable. This is normally used along with the `rmd-theme` function so that
/// both css variables and a fallback can be applied.
///
/// You are _most_ likely looking for the `rmd-theme` mixin and not the
/// functions instead.
///
/// @param {String} theme-name - The theme style to get. This should be one of
/// the keys from `$rmd-theme-values`.
/// @return {Color} the theme color.
@function rmd-theme-var($theme-name, $fallback-color: null) {
  @return rmd-theme-get-var(
    $theme-name,
    $rmd-theme-values,
    theme,
    $fallback-color
  );
}
