@use '../style/sass-utils';
@use './m3';
@use 'sass:map';

/// Generates a set of namespaced tokens for all components.
/// @param {Map} $systems The MDC system tokens
/// @param {Boolean} $include-non-systemized Whether to include non-systemized tokens
/// @param {Boolean} $include-density Whether to include density tokens
/// @return {Map} A map of namespaced tokens
@function generate-tokens($systems, $include-non-systemized: false, $include-density: false) {
  $systems: map.merge((
    md-sys-color: (),
    md-sys-elevation: (),
    md-sys-motion: (),
    md-sys-shape: (),
    md-sys-state: (),
    md-sys-typescale: ()
  ), $systems);
  $exclude-hardcoded: not $include-non-systemized;

  // TODO(mmalerba): Fill in remaining tokens.
  $result: sass-utils.deep-merge-all(
    // Add the system color & typography tokens (so we can give users access via an API).
    (
      (mat, theme): map.get($systems, md-sys-color),
      (mat, typography): map.get($systems, md-sys-typescale),
    ),
  );

  @return $result;
}

@function create-map($keys, $prefix) {
  $result: ();
  @each $key in $keys {
    $result: map.merge($result, ($key: var(--#{$prefix}-#{$key})));
  }
  @return $result;
}

@function get-sys-color($type, $palettes, $prefix) {
  $sys-color: null;

  @if ($type == dark) {
    $sys-color: m3.md-sys-color-values-dark($palettes);
  } @else {
    $sys-color: m3.md-sys-color-values-light($palettes);
  }

  @if (sass-utils.$use-system-color-variables) {
    $var-values: ();
    @each $key in map.keys($sys-color) {
      $var-values: map.set($var-values, $key, var(--#{$prefix}-#{$key}));
    }
    $var-values: map.set($var-values, shadow, map.get($sys-color, shadow));
    @return $var-values;
  }

  @return $sys-color;
}

@function get-sys-typeface($typography, $prefix) {
  $sys-typography: m3.md-sys-typescale-values($typography);
  @if (sass-utils.$use-system-typography-variables) {
    $var-values: ();
    @each $key in map.keys($sys-typography) {
      $var-values: map.set($var-values, $key, var(--#{$prefix}-#{$key}));
    }
    @return $var-values;
  }

  @return $sys-typography;
}

/// Generates a set of namespaced color tokens for all components.
/// @param {String} $type The type of theme system (light or dark)
/// @param {Map} $primary The primary palette
/// @param {Map} $tertiary The tertiary palette
/// @param {Map} $error The error palette
/// @param {String} $system-variables-prefix The prefix of system tokens
/// @return {Map} A map of namespaced color tokens
@function generate-color-tokens($type, $palettes, $system-variables-prefix) {
  $sys-color: get-sys-color($type, $palettes, $system-variables-prefix);

  @return generate-tokens((
    md-sys-color: $sys-color,
    md-ref-palette: (
      neutral-10: map.get($palettes, neutral, 10),
      neutral-variant20: map.get($palettes, neutral-variant, 20),
    ),
    // Because the elevation values are always combined with color values to create the box shadow,
    // elevation needs to be part of the color dimension.
    md-sys-elevation: m3.md-sys-elevation-values(),
    // Because the state values are sometimes combined with color values to create rgba colors,
    // state needs to be part of color dimension.
    // TODO(mmalerba): If at some point we remove the need for these combined values, we can move
    //  state to the base dimension.
    md-sys-state: m3.md-sys-state-values(),
  ));
}

/// Generates a set of namespaced color tokens for all components.
/// @param {String|List} $brand The brand font-family
/// @param {String|List} $plain The plain fort-family
/// @param {String|Number} $bold The bold font-weight
/// @param {String|Number} $medium The medium font-weight
/// @param {String|Number} $regular The regular font-weight
/// @param {String} $system-variables-prefix The prefix of system tokens
/// @return {Map} A map of namespaced typography tokens
@function generate-typography-tokens($typography, $system-variables-prefix) {
  $sys-typeface: get-sys-typeface($typography, $system-variables-prefix);
  @return generate-tokens((
    md-sys-typescale: $sys-typeface
  ));
}

/// Generates a set of namespaced tokens not related to color, typography, or density for all
/// components.
/// @return {Map} A map of namespaced tokens not related to color, typography, or density
@function generate-base-tokens() {
  // TODO(mmalerba): Exclude density tokens once implemented.
  @return generate-tokens((
    md-sys-motion: m3.md-sys-motion-values(),
    md-sys-shape: m3.md-sys-shape-values(),
  ), $include-non-systemized: true);
}
