/**
 * Styles for the BadgeIndicator component — a compact badge for communicating
 * count, status, or category. Supports three kinds: count (displays a number,
 * truncated at maxCount), marker (a plain status indicator), and icon (renders
 * a Beam icon inside the badge). Used across tabs, side navigation, notification
 * icons, avatars, and buttons.
 */

@use 'sass:map';
@use '../utils/animation.scss' as animation;
@use '../utils/constants.scss';
@use '../utils/mixins.scss' as mixins;
@use '../utils/tokens.scss' as tokens;
@use './badge.vars.scss' as vars;
@import '@viasat/beam-tokens/components/Badge';
@import '@viasat/beam-tokens/components/BadgeIndicator';

$badgeIndicatorBaseClass: '#{constants.$prefix}badge-indicator';
$ring-color: var(--#{constants.$prefix}comp-badge-indicator-ring-color, transparent);

$motion-duration: animation.duration('fast');

// `all 0s $snap-delay` snaps every box property at once; the entries after it win
// for transform and opacity (last match wins). Using `all` covers any property a
// future --hide-zero zeroes without editing this list.
@mixin collapse-transition($snap-delay) {
  transition: all 0s $snap-delay, transform $motion-duration ease,
    opacity $motion-duration ease;
}

// ─── Size map ────────────────────────────────────────────────────────────────
$sizes: (
  'sm': (
    'size': tokens.$bm-comp-badge-indicator-size-sm,
    'font': tokens.$bm-comp-badge-indicator-typo-sm,
    'icon': tokens.$bm-comp-badge-indicator-size-icon-sm,
    'marker': tokens.$bm-comp-badge-indicator-size-marker-sm,
  ),
  'md': (
    'size': tokens.$bm-comp-badge-indicator-size-md,
    'font': tokens.$bm-comp-badge-indicator-typo-md,
    'icon': tokens.$bm-comp-badge-indicator-size-icon-md,
    'marker': tokens.$bm-comp-badge-indicator-size-marker-md,
  ),
);

// ─── Color maps ──────────────────────────────────────────────────────────────
// The TSX applies appearance and emphasis as SEPARATE modifier classes
// (e.g. .bm-badge-indicator--positive + .bm-badge-indicator--strong).
// The @each loops below intersect those two classes to produce the right color.
//
// Count and icon color data (6 appearances × 3 emphases) is sourced from the
// shared badge.vars.scss map so Badge and BadgeIndicator stay in sync.

// Marker kind medium emphasis uses mute-ramp tokens — a softer tint specific to
// the marker context. Strong reuses the standard count/icon tokens (handled by the
// shared @each loop). Subtle is invalid in marker kind (TSX warns + falls back).
$markerMediumBg: (
  'positive': tokens.$bm-comp-badge-indicator-color-marker-positive-medium-bg,
  'warning': tokens.$bm-comp-badge-indicator-color-marker-warning-medium-bg,
  'negative': tokens.$bm-comp-badge-indicator-color-marker-negative-medium-bg,
  'infoPrimary': tokens.$bm-comp-badge-indicator-color-marker-info-primary-medium-bg,
  'infoSecondary':
    tokens.$bm-comp-badge-indicator-color-marker-info-secondary-medium-bg,
  'accent': tokens.$bm-comp-badge-indicator-color-marker-accent-medium-bg,
);

// ─── Component ────────────────────────────────────────────────────────────────

.#{$badgeIndicatorBaseClass} {
  // Base pill layout — shared by count and icon kinds.
  // Marker kind overrides dimensions in &--marker below.
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: tokens.$bm-comp-badge-indicator-radius;
  border-style: solid;
  border-width: tokens.$bm-comp-badge-border-width;
  padding-inline: tokens.$bm-comp-badge-indicator-space-x;
  overflow: hidden;
  white-space: nowrap;
  outline: tokens.$bm-sem-border-width-lg solid $ring-color;
  outline-offset: 0;

  // ── Sizes ────────────────────────────────────────────────────────────────
  // min-width equals height so single-digit counts remain circular (not oval).
  @each $size-name, $size in $sizes {
    &--#{$size-name} {
      height: map.get($size, 'size');
      min-width: map.get($size, 'size');
      font: map.get($size, 'font');

      .#{$badgeIndicatorBaseClass}__icon {
        width: map.get($size, 'icon');
        height: map.get($size, 'icon');
      }

      // Marker is a plain dot with its own dimensions, not a pill.
      &.#{$badgeIndicatorBaseClass}--marker {
        width: map.get($size, 'marker');
        height: map.get($size, 'marker');
        min-width: unset;
      }

      // Icon is square at the badge size; height comes from the pill rule.
      &.#{$badgeIndicatorBaseClass}--icon {
        width: map.get($size, 'size');
        min-width: unset;
      }
    }
  }

  // ── Marker and icon kinds ────────────────────────────────────────────────
  &--marker,
  &--icon {
    padding: 0;
  }

  &--marker {
    font: unset;
    overflow: visible;

    // Marker medium uses mute-ramp bg (softer than count/icon medium).
    // Strong reuses count/icon strong tokens (already generated by the @each below).
    @each $appearance, $bg in $markerMediumBg {
      &.#{$badgeIndicatorBaseClass}--#{$appearance}.#{$badgeIndicatorBaseClass}--medium {
        background-color: $bg;
        border-color: transparent;
      }
    }
  }

  // ── Icon wrapper ─────────────────────────────────────────────────────────
  // A wrapper <span> sits around the SVG; CSS sizes the span and the SVG
  // inherits those dimensions (follows the bm-badge__icon pattern).
  // Width/height per size are set via the size modifier blocks above.
  &__icon {
    display: inline-flex;
  }

  &__label {
    @include mixins.visually-hidden;
  }

  // ── Hide-zero ────────────────────────────────────────────────────────────
  // Transition lives on --collapsible, not the base class, so marker, icon, and
  // plain count carry none. No `transform: scale(1)` at rest — an identity
  // transform creates a stacking context and can blur text; CSS already reads a
  // missing transform as scale(1) when interpolating.
  &--collapsible {
    @include collapse-transition(0s);

    // Delayed so the badge finishes animating out before the box snaps to 0.
    &.#{$badgeIndicatorBaseClass}--hide-zero {
      @include collapse-transition($motion-duration);
    }
  }

  // opacity (not visibility/display) is intentional: it keeps the element in
  // layout as a zero-size box and does not suppress the nested aria-live span
  // from being monitored by screen readers.
  &--hide-zero {
    transform: scale(0);
    opacity: 0;
    width: 0;
    min-width: 0;
    height: 0;
    min-height: 0;
    padding: 0;
    border-width: 0;
  }

  // Both selectors are needed: --collapsible (0,1,0) can't override the
  // --collapsible.--hide-zero (0,2,0) rule declared outside this query.
  @media (prefers-reduced-motion: reduce) {
    &--collapsible,
    &--collapsible.#{$badgeIndicatorBaseClass}--hide-zero {
      transition: none;
    }
  }

  // ── Appearance × Emphasis colors ─────────────────────────────────────────
  // TSX applies appearance and emphasis as two separate BEM modifier classes.
  // These selectors intersect them: .bm-badge-indicator--positive.bm-badge-indicator--strong
  // Applies to all kinds (count, icon, marker-strong); marker-medium is overridden above.
  @each $appearance-name, $emphases in vars.$badgeColors {
    &--#{$appearance-name} {
      @each $emphasis-name, $c in $emphases {
        &.#{$badgeIndicatorBaseClass}--#{$emphasis-name} {
          background-color: map.get($c, bg);
          color: map.get($c, fg);
          border-color: map.get($c, border);
        }
      }
    }
  }
}
