@use './theming/theming';
@use './theming/inspection';
@use './theming/validation';
@use './ripple/ripple-theme';
@use './option/option-theme';
@use './option/optgroup-theme';
@use './selection/pseudo-checkbox/pseudo-checkbox-theme';
@use './style/sass-utils';
@use './typography/typography';
@use './tokens/token-utils';
@use './tokens/m2/mat/app' as tokens-mat-app;
@use './tokens/m2/mat/ripple' as tokens-mat-ripple;
@use './tokens/m2/mat/option' as tokens-mat-option;
@use './tokens/m2/mat/optgroup' as tokens-mat-optgroup;
@use './tokens/m2/mat/full-pseudo-checkbox' as tokens-mat-full-pseudo-checkbox;
@use './tokens/m2/mat/minimal-pseudo-checkbox' as tokens-mat-minimal-pseudo-checkbox;

@mixin base($theme) {
  @if inspection.get-theme-version($theme) == 1 {
    @include _theme-from-tokens(inspection.get-theme-tokens($theme, base));
  } @else {
    @include ripple-theme.base($theme);
    @include option-theme.base($theme);
    @include optgroup-theme.base($theme);
    @include pseudo-checkbox-theme.base($theme);
    @include sass-utils.current-selector-or-root() {
      @include token-utils.create-token-values(
        tokens-mat-app.$prefix,
        tokens-mat-app.get-unthemable-tokens()
      );
    }
  }
}

@mixin color($theme) {
  @if inspection.get-theme-version($theme) == 1 {
    @include _theme-from-tokens(inspection.get-theme-tokens($theme, color));
  } @else {
    @include ripple-theme.color($theme);
    @include option-theme.color($theme);
    @include optgroup-theme.color($theme);
    @include pseudo-checkbox-theme.color($theme);
    @include sass-utils.current-selector-or-root() {
      @include token-utils.create-token-values(
        tokens-mat-app.$prefix,
        tokens-mat-app.get-color-tokens($theme)
      );
    }
  }
}

@mixin typography($theme) {
  @if inspection.get-theme-version($theme) == 1 {
    @include _theme-from-tokens(inspection.get-theme-tokens($theme, typography));
  } @else {
    @include option-theme.typography($theme);
    @include optgroup-theme.typography($theme);
    @include pseudo-checkbox-theme.typography($theme);
    @include ripple-theme.typography($theme);
  }
}

@mixin density($theme) {
  @if inspection.get-theme-version($theme) == 1 {
    @include _theme-from-tokens(inspection.get-theme-tokens($theme, density));
  } @else {
    @include option-theme.density($theme);
    @include optgroup-theme.density($theme);
    @include pseudo-checkbox-theme.density($theme);
    @include ripple-theme.density($theme);
  }
}

@function _define-overrides() {
  $app-tokens: tokens-mat-app.get-token-slots();
  $ripple-tokens: tokens-mat-ripple.get-token-slots();
  $option-tokens: tokens-mat-option.get-token-slots();
  $optgroup-tokens: tokens-mat-optgroup.get-token-slots();
  $full-pseudo-checkbox-tokens: tokens-mat-full-pseudo-checkbox.get-token-slots();
  $minimal-pseudo-checkbox-tokens: tokens-mat-minimal-pseudo-checkbox.get-token-slots();

  @return (
    (namespace: tokens-mat-app.$prefix, tokens: $app-tokens, prefix: 'app-'),
    (namespace: tokens-mat-ripple.$prefix, tokens: $ripple-tokens, prefix: 'ripple-'),
    (namespace: tokens-mat-option.$prefix, tokens: $option-tokens, prefix: 'option-'),
    (namespace: tokens-mat-optgroup.$prefix, tokens: $optgroup-tokens, prefix: 'optgroup-'),
    (
      namespace: tokens-mat-full-pseudo-checkbox.$prefix,
      tokens: $full-pseudo-checkbox-tokens,
      prefix: 'pseudo-checkbox-full-'
    ),
    (
      namespace: tokens-mat-minimal-pseudo-checkbox.$prefix,
      tokens: $minimal-pseudo-checkbox-tokens,
      prefix: 'pseudo-checkbox-minimal-'
    )
  );
}

@mixin overrides($tokens: ()) {
  @include token-utils.batch-create-token-values($tokens, _define-overrides()...);
}

// Mixin that renders all of the core styles that depend on the theme.
@mixin theme($theme, $options...) {
  // Wrap the sub-theme includes in the duplicate theme styles mixin. This ensures that
  // there won't be multiple warnings. e.g. if `mat-core-theme` reports a warning, then
  // the imported themes (such as `mat-ripple-theme`) should not report again.
  @include theming.private-check-duplicate-theme-styles($theme, 'mat-core') {
    @if inspection.get-theme-version($theme) == 1 {
      @include _theme-from-tokens(inspection.get-theme-tokens($theme), $options...);
    } @else {
      @include base($theme);
      @if inspection.theme-has($theme, color) {
        @include color($theme);
      }
      @if inspection.theme-has($theme, density) {
        @include density($theme);
      }
      @if inspection.theme-has($theme, typography) {
        @include typography($theme);
      }
    }
  }
}

@mixin _theme-from-tokens($tokens, $options...) {
  @include validation.selector-defined(
    'Calls to Angular Material theme mixins with an M3 theme must be wrapped in a selector'
  );
  $mat-app-tokens: token-utils.get-tokens-for($tokens, tokens-mat-app.$prefix, $options...);
  $mat-ripple-tokens: token-utils.get-tokens-for($tokens, tokens-mat-ripple.$prefix, $options...);
  $mat-option-tokens: token-utils.get-tokens-for($tokens, tokens-mat-option.$prefix, $options...);
  $mat-optgroup-tokens: token-utils.get-tokens-for(
    $tokens,
    tokens-mat-optgroup.$prefix,
    $options...
  );
  $mat-full-pseudo-checkbox-tokens: token-utils.get-tokens-for(
    $tokens,
    tokens-mat-full-pseudo-checkbox.$prefix,
    $options...
  );
  $mat-minimal-pseudo-checkbox-tokens: token-utils.get-tokens-for(
    $tokens,
    tokens-mat-minimal-pseudo-checkbox.$prefix,
    $options...
  );

  @include token-utils.create-token-values(tokens-mat-app.$prefix, $mat-app-tokens);
  @include token-utils.create-token-values(tokens-mat-ripple.$prefix, $mat-ripple-tokens);
  @include token-utils.create-token-values(tokens-mat-option.$prefix, $mat-option-tokens);
  @include token-utils.create-token-values(tokens-mat-optgroup.$prefix, $mat-optgroup-tokens);
  @include token-utils.create-token-values(
    tokens-mat-full-pseudo-checkbox.$prefix,
    $mat-full-pseudo-checkbox-tokens
  );
  @include token-utils.create-token-values(
    tokens-mat-minimal-pseudo-checkbox.$prefix,
    $mat-minimal-pseudo-checkbox-tokens
  );
}
