// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@use "sass:map";
@import "../../common/mixins";
@import "../../common/variables";
@import "../../common/variables-extended";
@import "../progress-bar/common";

// N.B. Keeping existing SCSS variables for backward-compatibility.
// These are **not used** in button, and should be removed in
// the major version change.

$button-border-width: 1px !default;
$button-padding: $pt-spacing ($pt-spacing * 2) !default;
$button-padding-small: 0 ($pt-spacing * 2) !default;
$button-padding-large: $pt-spacing ($pt-spacing * 4) !default;
$button-icon-spacing: $pt-spacing * 2 !default;
$button-icon-spacing-large: $pt-spacing * 2 !default;

/*
CSS `border` property issues:
- An element can only have one border.
- Borders can't stack with shadows.
- Borders modify the size of the element they're applied to.
- Border positioning requires the extra `box-sizing` property.

`box-shadow` doesn't have these issues, we're using it instead of `border`.
*/
$button-box-shadow:
  inset 0 0 0 $button-border-width rgba($black, 0.2),
  0 1px 2px rgba($black, 0.1) !default;
$button-box-shadow-active:
  inset 0 0 0 $button-border-width rgba($black, 0.2),
  0 1px 2px rgba($black, 0.2) !default;

$dark-button-box-shadow:
  inset 0 0 0 $button-border-width rgba($white, 0.1),
  0 1px 2px rgba($black, 0.2) !default;
$dark-button-box-shadow-active:
  inset 0 0 0 $button-border-width rgba($white, 0.1),
  0 1px 2px rgba($black, 0.4) !default;

$button-color-disabled: $pt-text-color-disabled !default;
$button-background-color: $light-gray5 !default;
$button-background-color-hover: $light-gray4 !default;
$button-background-color-active: $light-gray2 !default;
$button-background-color-disabled: rgba($light-gray1, 0.5) !default;
$button-background-color-active-disabled: rgba($light-gray1, 0.7) !default;
$button-intent-color-disabled: rgba($white, 0.6);
$dark-button-color-disabled: $pt-dark-text-color-disabled !default;
$dark-button-background-color: $dark-gray3 !default;
$dark-button-background-color-hover: $dark-gray2 !default;
$dark-button-background-color-active: $dark-gray1 !default;
$dark-button-background-color-disabled: rgba($dark-gray3, 0.15) !default;
$dark-button-background-color-active-disabled: rgba($dark-gray3, 0.7) !default;
$dark-button-intent-color-disabled: rgba($white, 0.3);

$minimal-button-divider-width: 1px !default;
$minimal-button-background-color: none !default;
$minimal-button-background-color-hover: rgba($gray3, 0.15) !default;
$minimal-button-background-color-active: rgba($gray3, 0.3) !default;
$dark-minimal-button-background-color: none !default;
$dark-minimal-button-background-color-hover: rgba($gray3, 0.15) !default;
$dark-minimal-button-background-color-active: rgba($gray3, 0.3) !default;

$button-outlined-width: 1px !default;
$button-outlined-border-intent-opacity: 0.6 !default;
$button-outlined-border-disabled-intent-opacity: 0.2 !default;

// Temporary: warning button rest color needs a pre-computed fallback
// for browsers that don't support relative color syntax.
:root {
  --bp6-button-warning-rest: var(--bp-palette-orange-5); //#fbb360;
}

@supports (color: oklch(from var(--any-color) l c h)) {
  :root {
    --bp6-button-warning-rest: oklch(
      from var(--bp-intent-warning-rest) calc(l + 0.177) calc(c - 0.01) calc(h + 6.26)
    );
  }
}

// TODO(bp7): Replace with $button-intent-states
$button-intents: (
  "primary": (
    $blue3,
    $blue2,
    $blue1,
  ),
  "success": (
    $green3,
    $green2,
    $green1,
  ),
  "warning": (
    $orange3,
    $orange2,
    $orange1,
  ),
  "danger": (
    $red3,
    $red2,
    $red1,
  ),
) !default;

// Intent at each state
$button-intent-states: (
  "primary": (
    var(--bp-intent-primary-rest),
    var(--bp-intent-primary-hover),
    var(--bp-intent-primary-active),
    var(--bp-intent-primary-foreground),
  ),
  "success": (
    var(--bp-intent-success-rest),
    var(--bp-intent-success-hover),
    var(--bp-intent-success-active),
    var(--bp-intent-success-foreground),
  ),
  "warning": (
    var(--bp6-button-warning-rest),
    var(--bp-intent-warning-hover),
    var(--bp-intent-warning-active),
    var(--bp-intent-warning-foreground),
  ),
  "danger": (
    var(--bp-intent-danger-rest),
    var(--bp-intent-danger-hover),
    var(--bp-intent-danger-active),
    var(--bp-intent-danger-foreground),
  ),
  "default": (
    var(--bp-intent-default-rest),
    var(--bp-intent-default-hover),
    var(--bp-intent-default-active),
    var(--bp-intent-default-foreground),
  ),
) !default;

$button-intent-states: (
  "primary": (
    var(--bp-intent-primary-rest),
    var(--bp-intent-primary-hover),
    var(--bp-intent-primary-active),
    var(--bp-intent-primary-foreground),
  ),
  "success": (
    var(--bp-intent-success-rest),
    var(--bp-intent-success-hover),
    var(--bp-intent-success-active),
    var(--bp-intent-success-foreground),
  ),
  "warning": (
    var(--bp6-button-warning-rest),
    var(--bp-intent-warning-hover),
    var(--bp-intent-warning-active),
    var(--bp-intent-warning-foreground),
  ),
  "danger": (
    var(--bp-intent-danger-rest),
    var(--bp-intent-danger-hover),
    var(--bp-intent-danger-active),
    var(--bp-intent-danger-foreground),
  ),
  "default": (
    var(--bp-intent-default-rest),
    var(--bp-intent-default-hover),
    var(--bp-intent-default-active),
    var(--bp-intent-default-foreground),
  ),
) !default;

// Based off of `$pt-` variables in common/_mixins.scss
$button-intent-colors: (
  "primary": var(--bp-intent-primary-rest),
  "success": var(--bp-intent-success-rest),
  "warning": var(--bp6-button-warning-rest),
  "danger": var(--bp-intent-danger-rest),
  "default": var(--bp-intent-default-rest),
) !default;

$button-minimal-intent-text-colors: (
  "primary": var(--bp-intent-primary-hover),
  "success": var(--bp-intent-success-hover),
  "warning": var(--bp-intent-warning-hover),
  "danger": var(--bp-intent-danger-hover),
  "default": var(--bp-intent-default-hover),
) !default;

$button-intent-active-text-colors: (
  "primary": var(--bp-intent-primary-active),
  "success": var(--bp-intent-success-active),
  "warning": var(--bp-intent-warning-active),
  "danger": var(--bp-intent-danger-active),
  "default": var(--bp-intent-default-active),
) !default;

$button-dark-intent-text-colors: (
  "primary": color-mix(in oklch, var(--bp-intent-primary-rest) 51%, var(--bp-palette-white)),
  "success": color-mix(in oklch, var(--bp-intent-success-rest) 54%, var(--bp-palette-white)),
  "warning": color-mix(in oklch, var(--bp-intent-warning-rest) 53%, var(--bp-palette-white)),
  "danger": color-mix(in oklch, var(--bp-intent-danger-rest) 53%, var(--bp-palette-white)),
  // Use srgb for default intent to avoid hue shift with near-neutral gray
  "default": color-mix(in srgb, var(--bp-intent-default-rest) 46%, var(--bp-palette-white)),
) !default;

$button-dark-minimal-hover-text-colors: (
  "primary": color-mix(in oklch, var(--bp-intent-primary-hover) 51%, var(--bp-palette-white)),
  "success": color-mix(in oklch, var(--bp-intent-success-hover) 54%, var(--bp-palette-white)),
  "warning": color-mix(in oklch, var(--bp-intent-warning-hover) 53%, var(--bp-palette-white)),
  "danger": color-mix(in oklch, var(--bp-intent-danger-hover) 53%, var(--bp-palette-white)),
  // Use srgb for default intent to avoid hue shift with near-neutral gray
  "default": color-mix(in srgb, var(--bp-intent-default-hover) 46%, var(--bp-palette-white)),
) !default;

$button-dark-minimal-active-text-colors: (
  "primary": color-mix(in oklch, var(--bp-intent-primary-active) 51%, var(--bp-palette-white)),
  "success": color-mix(in oklch, var(--bp-intent-success-active) 54%, var(--bp-palette-white)),
  "warning": color-mix(in oklch, var(--bp-intent-warning-active) 53%, var(--bp-palette-white)),
  "danger": color-mix(in oklch, var(--bp-intent-danger-active) 53%, var(--bp-palette-white)),
  // Use srgb for default intent to avoid hue shift with near-neutral gray
  "default": color-mix(in srgb, var(--bp-intent-default-active) 46%, var(--bp-palette-white)),
) !default;

@mixin pt-button-layout() {
  @include pt-flex-container(row, calc(var(--bp-surface-spacing) * 2), $inline: inline);
  align-items: center;
  border: none;
  border-radius: var(--bp-surface-border-radius);
  cursor: pointer;
  font-size: var(--bp-typography-size-body-medium);
  justify-content: center;
  padding: var(--bp-surface-spacing) calc(var(--bp-surface-spacing) * 2);
  text-align: left;
  vertical-align: middle;
}

@mixin pt-button-height($height) {
  min-height: $height;
  min-width: $height;
}

@mixin pt-button-height-default() {
  min-height: calc(var(--bp-surface-spacing) * 7.5);
  min-width: calc(var(--bp-surface-spacing) * 7.5);
  padding: var(--bp-surface-spacing) calc(var(--bp-surface-spacing) * 2);
}

@mixin pt-button-height-small() {
  min-height: calc(var(--bp-surface-spacing) * 6);
  min-width: calc(var(--bp-surface-spacing) * 6);
  padding: 0 calc(var(--bp-surface-spacing) * 2);
}

// N.B. this mixin cannot be used on pseudo element selectors because it will produce invalid CSS
@mixin pt-button() {
  @include pt-button-default-colors;

  &:hover {
    @include pt-button-hover;
  }

  &:active,
  &.#{$ns}-active {
    @include pt-button-active;
  }

  &:disabled,
  &.#{$ns}-disabled {
    @include pt-button-disabled;

    &.#{$ns}-active,
    &.#{$ns}-active:hover {
      // Use srgb for consistency (avoids hue shift with near-neutral gray)
      background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 28%, transparent);
    }
  }

  @media (forced-colors: active) and (prefers-color-scheme: dark) {
    // Windows High Contrast dark theme
    border: 1px solid buttonborder;
  }
}

@mixin pt-button-default-colors() {
  // Use srgb for consistency with dark theme (avoids hue shift with near-neutral gray)
  background-color: color-mix(in srgb, var(--bp-intent-default-rest) 5%, var(--bp-palette-white));
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 10%, transparent);
  color: var(--bp-typography-color-default-rest);
}

@mixin pt-button-hover() {
  background-clip: padding-box;
  // Use srgb for consistency with dark theme (avoids hue shift with near-neutral gray)
  background-color: color-mix(in srgb, var(--bp-intent-default-hover) 9%, var(--bp-palette-white));
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 20%, transparent);
}

@mixin pt-button-active() {
  // Use srgb to avoid hue shift with near-neutral gray
  background-color: color-mix(
    in srgb,
    var(--bp-intent-default-active) 16%,
    var(--bp-palette-white)
  );
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 20%, transparent);

  @media (forced-colors: active) and (prefers-color-scheme: dark) {
    // Windows High Contrast dark theme
    background: highlight;
  }
}

@mixin pt-button-disabled() {
  // Use srgb for consistency with dark theme (avoids hue shift with near-neutral gray)
  background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 20%, transparent);
  box-shadow: none;
  color: var(--bp-typography-color-default-disabled);
  cursor: not-allowed;
  outline: none;
}

@mixin pt-button-intent(
  $default-color,
  $hover-color,
  $active-color,
  $text-color: var(--bp-palette-white)
) {
  background-color: $default-color;
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 10%, transparent);
  color: $text-color;

  &:hover,
  &:active,
  &.#{$ns}-active {
    color: $text-color;
  }

  &:hover {
    background-color: $hover-color;
    box-shadow:
      inset 0 0 0 var(--bp-surface-border-width)
        color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
      0 1px 2px color-mix(in oklch, var(--bp-palette-black) 20%, transparent);
  }

  &:active,
  &.#{$ns}-active {
    background-color: $active-color;
    box-shadow:
      inset 0 0 0 var(--bp-surface-border-width)
        color-mix(in oklch, var(--bp-surface-border-color-strong) 90%, var(--bp-palette-black)),
      0 1px 2px color-mix(in oklch, var(--bp-palette-black) 20%, transparent);
  }

  &:disabled,
  &.#{$ns}-disabled {
    background-color: color-mix(in oklch, $default-color 50%, transparent);
    border-color: transparent;
    box-shadow: none;
    color: color-mix(in oklch, $text-color 60%, transparent);

    @media (forced-colors: active) and (prefers-color-scheme: dark) {
      // Windows High Contrast dark theme
      border-color: graytext;
      color: graytext;
    }
  }

  @media (forced-colors: active) and (prefers-color-scheme: dark) {
    // Windows High Contrast dark theme
    border: 1px solid buttonborder;
    box-shadow: none;
  }
}

// N.B. this mixin cannot be used on pseudo element selectors because it will produce invalid CSS
@mixin pt-dark-button() {
  @include pt-dark-button-default-colors;

  &:hover,
  &:active,
  &.#{$ns}-active {
    // Use srgb to avoid hue shift with near-neutral gray
    color: color-mix(in srgb, var(--bp-intent-default-hover) 4%, var(--bp-palette-white));
  }

  &:hover {
    @include pt-dark-button-hover;
  }

  &:active,
  &.#{$ns}-active {
    @include pt-dark-button-active;
  }

  &:disabled,
  &.#{$ns}-disabled {
    @include pt-dark-button-disabled;

    &.#{$ns}-active {
      // Use srgb to avoid hue shift with near-neutral gray
      background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 7%, transparent);
    }
  }

  .#{$ns}-button-spinner .#{$ns}-spinner-head {
    // Use srgb to avoid hue shift with near-neutral gray
    background: color-mix(
      in srgb,
      var(--bp-intent-default-rest) 20%,
      var(--bp-palette-black)
    ); //$dark-progress-track-color;
    stroke: color-mix(
      in srgb,
      var(--bp-intent-default-rest) 68%,
      var(--bp-palette-white)
    ); //$dark-progress-head-color;
  }
}

@mixin pt-dark-button-default-colors() {
  // Use srgb to avoid hue shift with near-neutral gray
  background-color: color-mix(in srgb, var(--bp-intent-default-rest) 40%, var(--bp-palette-black));
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-default) 50%, transparent),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 20%, transparent);
  color: var(--bp-intent-default-foreground);
}

@mixin pt-dark-button-hover() {
  // Use srgb instead of oklch to avoid hue shift with near-neutral dark colors
  background-color: color-mix(in srgb, var(--bp-intent-default-hover) 42%, var(--bp-palette-black));
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-default) 50%, transparent),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 40%, transparent);
}

@mixin pt-dark-button-active() {
  // Use srgb instead of oklch to avoid hue shift with near-neutral dark colors
  background-color: color-mix(
    in srgb,
    var(--bp-intent-default-active) 30%,
    var(--bp-palette-black)
  );
  box-shadow:
    inset 0 0 0 var(--bp-surface-border-width)
      color-mix(in oklch, var(--bp-surface-border-color-default) 50%, transparent),
    0 1px 2px color-mix(in oklch, var(--bp-palette-black) 40%, transparent);
}

@mixin pt-dark-button-disabled() {
  // Use srgb to avoid hue shift with near-neutral gray
  background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 4%, transparent);
  box-shadow: none;
  color: var(--bp-typography-color-default-disabled);
}

@mixin pt-button-minimal() {
  background: none;
  box-shadow: none;

  &:hover {
    // Use srgb instead of oklch to avoid hue shift with near-neutral colors
    background-color: color-mix(in srgb, var(--bp-intent-default-hover) 8%, transparent);
    box-shadow: none;
    color: var(--bp-typography-color-default-rest);
    text-decoration: none;
  }

  &:active,
  &.#{$ns}-active {
    // Use srgb instead of oklch to avoid hue shift with near-neutral colors
    background-color: color-mix(in srgb, var(--bp-intent-default-active) 16%, transparent);
    box-shadow: none;
    color: var(--bp-typography-color-default-rest);
  }

  &:disabled,
  &:disabled:hover,
  &.#{$ns}-disabled,
  &.#{$ns}-disabled:hover {
    background: none;
    color: var(--bp-typography-color-default-disabled);
    cursor: not-allowed;

    &.#{$ns}-active {
      background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 30%, transparent);
    }
  }

  .#{$ns}-dark &,
  [data-bp-color-scheme="dark"] & {
    background: none;
    box-shadow: none;
    color: var(--bp-intent-default-foreground);

    &:hover,
    &:active,
    &.#{$ns}-active {
      background: none;
      box-shadow: none;
      color: var(--bp-intent-default-foreground);
    }

    &:hover {
      // Use srgb instead of oklch to avoid hue shift with near-neutral colors
      // TODO(BP7): Update this semantic token to use `--bp-intent-default-hover`
      background-color: color-mix(in srgb, var(--bp-intent-default-rest) 24%, transparent);
    }

    &:active,
    &.#{$ns}-active {
      // Use srgb instead of oklch to avoid hue shift with near-neutral colors
      // TODO(BP7): Update this semantic token to use `--bp-intent-default-active`
      background-color: color-mix(in srgb, var(--bp-intent-default-rest) 49%, transparent);
    }

    &:disabled,
    &:disabled:hover,
    &.#{$ns}-disabled,
    &.#{$ns}-disabled:hover {
      background: none;
      color: var(--bp-typography-color-default-disabled);
      cursor: not-allowed;

      &.#{$ns}-active {
        background-color: color-mix(in srgb, var(--bp-intent-default-disabled) 30%, transparent);
      }
    }
  }

  @each $intent, $colors in $button-intent-states {
    &.#{$ns}-intent-#{$intent} {
      @include pt-button-minimal-intent($intent);
    }
  }
}

@mixin pt-button-minimal-intent($intent) {
  $intent-color: map.get($button-intent-colors, $intent);
  $text-color: map.get($button-minimal-intent-text-colors, $intent);
  $active-text-color: map.get($button-intent-active-text-colors, $intent);
  $dark-text-color: map.get($button-dark-intent-text-colors, $intent);
  $dark-hover-text-color: map.get($button-dark-minimal-hover-text-colors, $intent);
  $dark-active-text-color: map.get($button-dark-minimal-active-text-colors, $intent);

  color: $text-color;

  &:hover,
  &:active,
  &.#{$ns}-active {
    background: none;
    box-shadow: none;
    color: $text-color;
  }

  &:hover {
    background-color: color-mix(in oklch, $intent-color 15%, transparent);
    color: $text-color;
  }

  &:active,
  &.#{$ns}-active {
    background-color: color-mix(in oklch, $intent-color 30%, transparent);
    color: $active-text-color;
  }

  &:disabled,
  &.#{$ns}-disabled {
    background: none;
    color: color-mix(in oklch, $text-color 50%, transparent);

    &.#{$ns}-active {
      background-color: color-mix(in oklch, $intent-color 30%, transparent);
    }
  }

  .#{$ns}-button-spinner .#{$ns}-spinner-head {
    stroke: $text-color;
  }

  .#{$ns}-dark &,
  [data-bp-color-scheme="dark"] & {
    color: $dark-text-color;

    &:hover {
      background-color: color-mix(in oklch, $intent-color 20%, transparent);
      color: $dark-hover-text-color;
    }

    &:active,
    &.#{$ns}-active {
      background-color: color-mix(in oklch, $intent-color 30%, transparent);
      color: $dark-active-text-color;
    }

    &:disabled,
    &.#{$ns}-disabled {
      background: none;
      color: color-mix(in oklch, $dark-text-color 50%, transparent);

      &.#{$ns}-active {
        background-color: color-mix(in oklch, $intent-color 30%, transparent);
      }
    }
  }
}

@mixin pt-button-outlined() {
  border: var(--bp-surface-border-width) solid var(--bp-surface-border-color-strong);
  box-sizing: border-box;

  &:disabled,
  &:disabled:hover,
  &.#{$ns}-disabled,
  &.#{$ns}-disabled:hover {
    border-color: var(--bp-surface-border-color-default);
  }

  .#{$ns}-dark &,
  [data-bp-color-scheme="dark"] & {
    border-color: var(--bp-surface-border-color-strong);

    &:disabled,
    &:disabled:hover,
    &.#{$ns}-disabled,
    &.#{$ns}-disabled:hover {
      border-color: var(--bp-surface-border-color-default);
    }
  }

  @each $intent, $colors in $button-intent-states {
    $text-color: map.get($button-minimal-intent-text-colors, $intent);
    $dark-text-color: map.get($button-dark-intent-text-colors, $intent);

    &.#{$ns}-intent-#{$intent} {
      @include pt-button-outlined-intent($text-color, $dark-text-color);
    }
  }
}

@mixin pt-button-outlined-intent($text-color, $dark-text-color) {
  border-color: color-mix(in oklch, $text-color 60%, transparent);

  &:disabled,
  &.#{$ns}-disabled {
    border-color: color-mix(in oklch, $text-color 20%, transparent);
  }

  .#{$ns}-dark &,
  [data-bp-color-scheme="dark"] & {
    border-color: color-mix(in oklch, $dark-text-color 60%, transparent);

    &:disabled,
    &.#{$ns}-disabled {
      border-color: color-mix(in oklch, $dark-text-color 20%, transparent);
    }
  }
}
