//
// Copyright IBM Corp. 2016, 2024
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@use 'sass:math';
@use 'tokens' as *;
@use 'vars' as *;
@use 'mixins' as *;
@use '../tooltip';
@use '../../config' as *;
@use '../../spacing' as *;
@use '../../theme' as *;
@use '../../type' as *;
@use '../../layer' as *;
@use '../../utilities/convert';
@use '../../utilities/focus-outline';
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/skeleton' as *;
@use '../../utilities/visually-hidden' as *;
@use '../../utilities/layout';

@function has-n-children($n) {
  // Uses nth-child() to select the nth child, and :last-child to ensure that
  // the selector only matches the last child of its parent.
  @return ':has(:nth-child(#{$n}):last-child)';
}

@mixin button-set-fluid-column() {
  --flex-direction: column;

  .#{$prefix}--btn {
    flex: initial;
    inline-size: 100%;
    max-inline-size: none;
  }

  .#{$prefix}--btn--ghost {
    padding-inline-start: $spacing-05;
  }
}

@mixin button-set-fluid-layout() {
  container-type: inline-size;

  .#{$prefix}--btn-set__fluid-inner {
    --flex-direction: row;

    display: flex;
    flex-direction: var(--flex-direction);
    align-items: stretch;
    justify-content: flex-end;
    inline-size: 100%;
  }

  // NOTE: Container queries are based on this value which is based on IBM Products implementation
  // Side panel has up to 3 buttons unstacked from size lg (640px). Min 160.33px/button
  // Narrow Tearsheet 540px has 4 buttons unstacked buttons. Min 135px/button
  // May need to be configurable as 3 * 135px is less than 640px.
  // Current value 176px only supports up to 3 buttons at 540px.
  $min-inline-button-size: convert.to-rem(176px);

  .#{$prefix}--btn-set__fluid-inner .#{$prefix}--btn {
    // default non-column layout
    flex: 0 1 25%;

    // This increased size comes from use in IBM Products Tearsheet and SidePanel
    max-inline-size: convert.to-rem(232px);
  }

  .#{$prefix}--btn-set__fluid-inner--auto-stack .#{$prefix}--btn {
    min-inline-size: $min-inline-button-size;
  }

  .#{$prefix}--btn-set__fluid-inner .#{$prefix}--btn--ghost,
  .#{$prefix}--btn-set__fluid-inner .#{$prefix}--btn--danger--ghost {
    // ghost buttons always grow to fill the container
    flex: 1 1 25%;
    max-inline-size: none;
    padding-inline-start: $spacing-07; /* increased padding when inline */
  }

  $max-fluid-buttons: 4;
  // this determines whether or not column is used
  @for $i from 1 through $max-fluid-buttons {
    @container (width <= #{$i * $min-inline-button-size}) {
      .#{$prefix}--btn-set__fluid-inner--auto-stack#{has-n-children($i)} {
        @include button-set-fluid-column();
      }
    }
  }

  @container (width <= #{4 * $min-inline-button-size}) {
    .#{$prefix}--btn-set__fluid-inner#{has-n-children(2)} {
      .#{$prefix}--btn {
        flex-basis: 50%;
        max-inline-size: none;
      }
    }
  }

  @container (width <= #{3 * $min-inline-button-size}) {
    .#{$prefix}--btn-set__fluid-inner#{has-n-children(1)} .#{$prefix}--btn {
      flex: 1 1 100%;
      max-inline-size: none;
    }
  }
}

@mixin button {
  .#{$prefix}--btn {
    @include layout.use('size', $min: 'xs', $default: 'lg', $max: '2xl');
    @include layout.use('density', $default: 'normal');

    @include button-base;
  }

  // Reset intrinsic padding in Firefox (see #731)
  .#{$prefix}--btn::-moz-focus-inner {
    padding: 0;
    border: 0;
  }

  .#{$prefix}--btn--primary {
    @include button-theme(
      $button-primary,
      transparent,
      $text-on-color,
      $button-primary-hover,
      currentColor,
      $button-primary-active
    );

    &:hover {
      color: $text-on-color;
    }
  }

  .#{$prefix}--btn--secondary {
    @include button-theme(
      $button-secondary,
      transparent,
      $text-on-color,
      $button-secondary-hover,
      currentColor,
      $button-secondary-active
    );

    &:hover,
    &:focus {
      color: $text-on-color;
    }
  }

  .#{$prefix}--btn--tertiary {
    @include button-theme(
      transparent,
      $button-tertiary,
      $button-tertiary,
      $button-tertiary-hover,
      currentColor,
      $button-tertiary-active
    );

    @media (any-hover: hover) {
      &:hover {
        color: $text-inverse;
      }
    }

    &:focus {
      background-color: $button-tertiary;
      color: $text-inverse;
    }

    &:active {
      border-color: transparent;
      background-color: $button-tertiary-active;
      color: $text-inverse;
    }

    &:disabled,
    &:hover:disabled,
    &:focus:disabled,
    &.#{$prefix}--btn--disabled,
    &.#{$prefix}--btn--disabled:hover,
    &.#{$prefix}--btn--disabled:focus {
      background: transparent;
      color: $text-disabled;
      outline: none;
    }
  }

  .#{$prefix}--btn--ghost {
    @include button-theme(
      transparent,
      transparent,
      $link-primary,
      $background-hover,
      currentColor,
      $background-active
    );

    padding-inline-end: calc(
      layout.density('padding-inline') - convert.to-rem(1px)
    );

    .#{$prefix}--btn__icon {
      position: static;
      align-self: center;
      margin-inline-start: $spacing-03;
    }

    // Apply hover styles only on devices that support hover
    @media (hover: hover) {
      &:hover {
        color: $link-primary-hover;
      }
    }

    &:active {
      background-color: $background-active;
      color: $link-primary-hover;
    }

    &:disabled,
    &:hover:disabled,
    &:focus:disabled,
    &.#{$prefix}--btn--disabled,
    &.#{$prefix}--btn--disabled:hover,
    &.#{$prefix}--btn--disabled:focus {
      border-color: transparent;
      background: transparent;
      color: $text-disabled;
      outline: none;
    }

    &:not([disabled]) svg {
      fill: $icon-primary;
    }
  }

  .#{$prefix}--btn--icon-only {
    align-items: center;
    justify-content: center;
    padding: 0;
    block-size: layout.size('height');
    inline-size: layout.size('height');
    padding-block-start: 0;

    > :first-child {
      min-inline-size: convert.to-rem(16px);
    }

    .#{$prefix}--btn__icon {
      position: static;
    }

    &.#{$prefix}--btn--ghost {
      &:focus {
        background-color: $background-active;
        box-shadow: inset 0 0 0 $button-outline-width $button-focus-color;
      }
    }

    &.#{$prefix}--btn--ghost .#{$prefix}--btn__icon,
    &.#{$prefix}--btn--danger--ghost .#{$prefix}--btn__icon {
      margin: 0;
    }

    &.#{$prefix}--btn--danger--ghost {
      padding-inline-end: calc(
        layout.density('padding-inline') - convert.to-rem(16px)
      );
    }
  }

  // Adjust text positioning in extra small variant only
  .#{$prefix}--btn--xs:not(.#{$prefix}--btn--icon-only) {
    padding-block-start: 1.5px;
  }

  // Adjust icon positioning in extra small, small, medium variants only
  .#{$prefix}--btn--xs:not(.#{$prefix}--btn--icon-only) .#{$prefix}--btn__icon,
  .#{$prefix}--btn--sm:not(.#{$prefix}--btn--icon-only) .#{$prefix}--btn__icon,
  .#{$prefix}--btn--md:not(.#{$prefix}--btn--icon-only) .#{$prefix}--btn__icon {
    margin-block-start: 0;
  }

  .#{$prefix}--btn--icon-only.#{$prefix}--btn--selected {
    background: $background-selected;
  }

  .#{$prefix}--btn path[data-icon-path='inner-path'] {
    fill: none;
  }

  .#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only
    .#{$prefix}--btn__icon
    path:not([data-icon-path]):not([fill='none']),
  .#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only .#{$prefix}--btn__icon {
    fill: $icon-primary;
  }

  .#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only[disabled]
    .#{$prefix}--btn__icon
    path:not([data-icon-path]):not([fill='none']),
  .#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only[disabled]
    .#{$prefix}--btn__icon,
  .#{$prefix}--btn.#{$prefix}--btn--icon-only.#{$prefix}--btn--ghost[disabled]:hover
    .#{$prefix}--btn__icon {
    fill: $icon-on-color-disabled;
  }

  .#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only[disabled] {
    cursor: not-allowed;
  }

  // Workaround to ensure onMouseEnter events fire when moving
  // from a disabled button to a non-disabled button (#13815)
  .#{$prefix}--icon-tooltip--disabled .#{$prefix}--tooltip-trigger__wrapper {
    cursor: not-allowed;
  }

  .#{$prefix}--icon-tooltip--disabled .#{$prefix}--btn--icon-only[disabled] {
    pointer-events: none;
  }

  .#{$prefix}--btn--danger {
    @include button-theme(
      $button-danger-primary,
      transparent,
      $text-on-color,
      $button-danger-hover,
      currentColor,
      $button-danger-active
    );

    &:hover {
      color: $text-on-color;
    }

    &--tertiary {
      @include button-theme(
        transparent,
        $button-danger-secondary,
        $button-danger-secondary,
        $button-danger-hover,
        currentColor,
        $button-danger-active
      );

      @media (hover: hover) {
        &:hover {
          border-color: $button-danger-hover;
          color: $text-on-color;
        }
      }

      &:focus {
        background-color: $button-danger-primary;
        color: $text-on-color;
      }

      &:active {
        border-color: $button-danger-active;
        background-color: $button-danger-active;
        color: $text-on-color;
      }

      &:disabled,
      &:hover:disabled,
      &:focus:disabled,
      &.#{$prefix}--btn--disabled,
      &.#{$prefix}--btn--disabled:hover,
      &.#{$prefix}--btn--disabled:focus {
        background: transparent;
        color: $text-disabled;
        outline: none;
      }
    }

    &--ghost {
      @include button-theme(
        transparent,
        transparent,
        $button-danger-secondary,
        $button-danger-hover,
        currentColor,
        $button-danger-active
      );

      padding-inline-end: calc(
        layout.density('padding-inline') - convert.to-rem(1px)
      );

      .#{$prefix}--btn__icon {
        position: static;
        margin-inline-start: $spacing-03;
      }

      @media (hover: hover) {
        &:hover {
          color: $text-on-color;
        }
      }

      &:active {
        color: $text-on-color;
      }

      &:disabled,
      &:hover:disabled,
      &:focus:disabled,
      &.#{$prefix}--btn--disabled,
      &.#{$prefix}--btn--disabled:hover,
      &.#{$prefix}--btn--disabled:focus {
        border-color: transparent;
        background: transparent;
        color: $text-disabled;
        outline: none;
      }
    }
  }

  //expressive styles
  .#{$prefix}--btn--expressive {
    @include type-style('body-compact-02');

    padding-block: min(
      calc(
        (layout.size('height') - var(--temp-expressive-1lh)) / 2 - convert.to-rem(
            1px
          )
      ),
      var(--temp-padding-block-max)
    );
  }

  .#{$prefix}--btn--icon-only.#{$prefix}--btn--expressive {
    padding: 12px 13px;
    //default size 48px
  }

  .#{$prefix}--btn.#{$prefix}--btn--expressive .#{$prefix}--btn__icon {
    block-size: convert.to-rem(20px);
    inline-size: convert.to-rem(20px);
  }

  .#{$prefix}--btn-set .#{$prefix}--btn.#{$prefix}--btn--expressive {
    max-inline-size: convert.to-rem(320px);
  }

  // Skeleton State
  .#{$prefix}--btn.#{$prefix}--skeleton {
    @include skeleton;

    inline-size: convert.to-rem(150px);
  }

  // button set styles
  .#{$prefix}--btn-set {
    display: flex;
  }

  .#{$prefix}--btn-set--stacked {
    flex-direction: column;
  }

  .#{$prefix}--btn-set .#{$prefix}--btn {
    inline-size: 100%;
    // 196px from design kit
    max-inline-size: convert.to-rem(196px);

    &:not(:focus) {
      box-shadow: convert.to-rem(-1px) 0 0 0 $button-separator;
    }

    &:first-of-type:not(:focus) {
      box-shadow: inherit;
    }
  }

  .#{$prefix}--btn-set .#{$prefix}--btn:focus + .#{$prefix}--btn {
    box-shadow: inherit;
  }

  .#{$prefix}--btn-set--stacked .#{$prefix}--btn:not(:focus) {
    box-shadow: 0 convert.to-rem(-1px) 0 0 $button-separator;
  }

  .#{$prefix}--btn-set--stacked .#{$prefix}--btn:first-of-type:not(:focus) {
    box-shadow: inherit;
  }

  .#{$prefix}--btn-set .#{$prefix}--btn.#{$prefix}--btn--disabled {
    box-shadow: convert.to-rem(-1px) 0 0 0 $icon-on-color-disabled;

    &:first-of-type {
      box-shadow: none;
    }
  }

  .#{$prefix}--btn-set--stacked .#{$prefix}--btn.#{$prefix}--btn--disabled {
    box-shadow: 0 convert.to-rem(-1px) 0 0 $layer-selected-disabled;

    &:first-of-type {
      box-shadow: none;
    }
  }

  .#{$prefix}--btn-set .#{$prefix}--btn.#{$prefix}--btn--loading {
    border-color: transparent;
    background-color: transparent;
    box-shadow: none;
  }

  // badge indicator

  .#{$prefix}--btn--sm .#{$prefix}--badge-indicator {
    margin-block-start: $spacing-02;
    margin-inline-end: $spacing-02;
  }

  // Windows HCM fix
  .#{$prefix}--btn:focus {
    @include high-contrast-mode('focus');
  }

  // RTL overrides
  [dir='rtl'] .#{$prefix}--btn-set .#{$prefix}--btn:not(:focus) {
    box-shadow: convert.to-rem(1px) 0 0 0 $button-separator;
  }

  .#{$prefix}--btn-set--fluid {
    @include button-set-fluid-layout();
  }
}
