@use 'sass:map';
@use 'sass:meta';
@use '@angular/material' as mat;
@use '../../alert/m2-alert';
@use '../../colorpicker/m2-colorpicker';
@use '../../datetimepicker/m2-datetimepicker';
@use '../../drawer/m2-drawer';
@use '../../grid/m2-grid';
@use '../../loader/m2-loader';
@use '../../popover/m2-popover';
@use '../../progress/m2-progress';
@use '../../select/m2-select';
@use '../../split/m2-split';
@use '../../tooltip/m2-tooltip';

/// Gets the tokens for the given theme, m2 tokens module, and theming system.
/// @param {Map} $theme The Angular Material theme object to generate token values from.
/// @param {String} $module The Sass module containing the token getter functions.
/// @param {String} $system The theming system to get tokens for. Valid values are: unthemable,
///     color, typography, density.
/// @return {Map} The token map by calling the token getter for the given system in the given module
///    with the given Angular Material theme. Token names are not fully-qualified.
@function _get-tokens-for-module-and-system($theme, $module, $system) {
  @if $system == unthemable {
    @return meta.call(
        meta.get-function(get-#{$system}-tokens, $module: $module));
  }
  @if not mat.theme-has($theme, $system) {
    @return ();
  }
  @return meta.call(
      meta.get-function(get-#{$system}-tokens, $module: $module), $theme);
}

/// Gets the fully qualified tokens map for the given theme and m2 tokens module.
/// @param {Map} $theme The Angular Material theme object to generate token values from.
/// @param {String} $module The Sass module containing the token getter functions.
/// @return {Map} The token map by calling the token getters in the given module with the given
///     Angular Material theme. Token names are fully-qualified.
@function _get-tokens-for-module($theme, $module) {
  $tokens: mat.private-deep-merge-all(
      _get-tokens-for-module-and-system($theme, $module, unthemable),
      _get-tokens-for-module-and-system($theme, $module, color),
      _get-tokens-for-module-and-system($theme, $module, typography),
      _get-tokens-for-module-and-system($theme, $module, density));
  @return map.set((), map.get(meta.module-variables($module), prefix), $tokens);
}

/// Gets the full set of M2 tokens for the given theme object.
/// @param {Map} $theme The Angular Material theme object to generate token values from.
/// @return {Map} The token map for the given Angular Material theme. Returned format:
///     (
///       (fully, qualified, namespace): (
///         token: value
///       )
///     )
@function m2-tokens-from-theme($theme) {
  @return mat.private-deep-merge-all(
    _get-tokens-for-module($theme, m2-alert),
    _get-tokens-for-module($theme, m2-colorpicker),
    _get-tokens-for-module($theme, m2-datetimepicker),
    _get-tokens-for-module($theme, m2-drawer),
    _get-tokens-for-module($theme, m2-grid),
    _get-tokens-for-module($theme, m2-loader),
    _get-tokens-for-module($theme, m2-popover),
    _get-tokens-for-module($theme, m2-progress),
    _get-tokens-for-module($theme, m2-select),
    _get-tokens-for-module($theme, m2-split),
    _get-tokens-for-module($theme, m2-tooltip),
  );
}
