@use './theming/theming';
@use './theming/inspection';
@use './theming/validation';
@use './style/private';
@use './ripple/ripple-theme';
@use './option/option-theme';
@use './option/optgroup-theme';
@use './selection/pseudo-checkbox/pseudo-checkbox-theme';
@use './style/elevation';
@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/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);
  }
}

@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));
    }

    // Provides external CSS classes for each elevation value. Each CSS class is formatted as
    // `mat-elevation-z$zValue` where `$zValue` corresponds to the z-space to which the element is
    // elevated.
    @for $zValue from 0 through 24 {
      $selector: elevation.$prefix + $zValue;
      // We need the `mat-mdc-elevation-specific`, because some MDC mixins
      // come with elevation baked in and we don't have a way of removing it.
      .#{$selector}, .mat-mdc-elevation-specific.#{$selector} {
        @include private.private-theme-elevation($zValue, $theme);
      }
    }
  }

  // TODO(crisbeto): move this into the base.
  // Marker that is used to determine whether the user has added a theme to their page.
  @at-root {
    .mat-theme-loaded-marker {
      display: none;
    }
  }
}

@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);
  }
}

// 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-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-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);
}
