@use 'sass:map';
@use '../utils/constants.scss';
@use '../utils/tokens.scss' as tokens;
@use '../utils/mixins.scss' as mixins;
@use '../utils/cursors.scss' as cursors;
@use './icon.vars.scss' as iconVars;
@use './input.vars.scss' as inputVars;

@import '@viasat/beam-tokens/components/Input';

$comboboxBaseClass: '#{constants.$prefix}combobox';

$expandIconWidth: 0.625rem;
$expandIconHeight: 0.3125rem;
$expandIcon: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iNSIgdmlld0JveD0iMCAwIDEwIDUiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0wLjE4MjgzMiAwLjMxMjQ2NEMwLjExNDQwOSAwLjM5NzkxNSAwLjA2MzQ5MzEgMC40OTYwMSAwLjAzMjk5NCAwLjYwMTE0NUMwLjAwMjQ5NDk0IDAuNzA2MjggLTAuMDA2OTg5NjIgMC44MTYzOTUgMC4wMDUwODIyOCAwLjkyNTE5NkMwLjAxNzE1NDIgMS4wMzQgMC4wNTA1NDU5IDEuMTM5MzYgMC4xMDMzNSAxLjIzNTI1QzAuMTU2MTUzIDEuMzMxMTQgMC4yMjczMzQgMS40MTU2OSAwLjMxMjgyNSAxLjQ4NDA2TDQuNDc5MjUgNC44MTcyQzQuNjI3MDQgNC45MzU1MyA0LjgxMDcyIDUgNS4wMDAwNSA1QzUuMTg5MzcgNSA1LjM3MzA2IDQuOTM1NTMgNS41MjA4NSA0LjgxNzJMOS42ODcyNyAxLjQ4NDA2QzkuODU5ODcgMS4zNDU5NCA5Ljk3MDU0IDEuMTQ0OSA5Ljk5NDkxIDAuOTI1MTg1QzEwLjAxOTMgMC43MDU0NjggOS45NTUzOSAwLjQ4NTA2NiA5LjgxNzI2IDAuMzEyNDY0QzkuNjc5MTQgMC4xMzk4NjMgOS40NzgxIDAuMDI5MjAwNyA5LjI1ODM5IDAuMDA0ODIyNDJDOS4wMzg2NyAtMC4wMTk1NTU5IDguODE4MjcgMC4wNDQzNDY1IDguNjQ1NjcgMC4xODI0NzJMNS4wMDAwNSAzLjA5ODk3TDEuMzU0NDMgMC4xODI0NzJDMS4yNjg5OCAwLjExNDA0OCAxLjE3MDg4IDAuMDYzMTMzIDEuMDY1NzUgMC4wMzI2MzM5QzAuOTYwNjE0IDAuMDAyMTM0ODEgMC44NTA1IC0wLjAwNzM1MDQgMC43NDE2OTggMC4wMDQ3MjE1QzAuNjMyODk2IDAuMDE2NzkzNCAwLjUyNzUzOSAwLjA1MDE4NTggMC40MzE2NDYgMC4xMDI5ODlDMC4zMzU3NTQgMC4xNTU3OTMgMC4yNTEyMDYgMC4yMjY5NzQgMC4xODI4MzIgMC4zMTI0NjRWMC4zMTI0NjRaIiBmaWxsPSJibGFjayIvPgo8L3N2Zz4K');

$labelSpaceBottom: '--#{constants.$prefix}label-space-bottom';
$helperTextSpaceTop: '--#{constants.$prefix}helper-text-space-top';

$comboboxCursor: '--#{constants.$prefix}text-field-cursor';
$comboboxInputCursor: '--#{constants.$prefix}text-field-input-cursor';

$comboboxDropdownMaxItemsVar: '--#{constants.$prefix}combobox-dropdown-max-items';

$stateStyleTokens: (
  error: (
    textColor: tokens.$bm-comp-input-color-text,
    backgroundColor: tokens.$bm-comp-input-color-bg,
    borderColor: tokens.$bm-comp-input-color-border-error,
    expandIconColor: tokens.$bm-comp-input-color-icon,
  ),
  read-only: (
    textColor: tokens.$bm-comp-input-color-text,
    backgroundColor: tokens.$bm-comp-input-color-bg-disabled,
    borderColor: tokens.$bm-comp-input-color-border-disabled,
    expandIconColor: tokens.$bm-comp-input-color-icon-disabled,
  ),
  disabled: (
    textColor: tokens.$bm-comp-input-color-text-disabled,
    backgroundColor: tokens.$bm-comp-input-color-bg-disabled,
    borderColor: tokens.$bm-comp-input-color-border-disabled,
    expandIconColor: tokens.$bm-comp-input-color-icon-disabled,
  ),
);

.#{$comboboxBaseClass} {
  @include cursors.applyTextCursors();
  max-width: tokens.$bm-comp-input-size-field-width;
  position: relative;

  #{$labelSpaceBottom}: #{tokens.$bm-comp-label-space-bottom};
  #{$helperTextSpaceTop}: #{tokens.$bm-comp-helper-text-space-top};

  @include inputVars.field-size-scale;

  &--fluid {
    max-width: 100%;
  }

  &--autocomplete &__field {
    #{$comboboxInputCursor}: text;
  }

  &--disabled,
  &--disabled &__field {
    #{$comboboxCursor}: not-allowed;
    #{$comboboxInputCursor}: not-allowed;
  }

  &--multiple:not(&--autocomplete):not(&--empty) &__field__input {
    display: none;
  }

  &:not(&--autocomplete) &__field::selection {
    background-color: transparent;
  }

  &__field {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    position: relative;
    cursor: var(#{$comboboxCursor}, pointer);
    user-select: none;
    font: var(#{inputVars.$fieldFont});
    min-height: var(#{inputVars.$fieldHeight});
    gap: tokens.$bm-comp-input-space-field-gap;
    #{iconVars.$iconColor}: tokens.$bm-comp-input-color-icon;
    #{iconVars.$iconSize}: var(#{inputVars.$fieldIconSize});

    &__chevron {
      position: absolute;
      cursor: var(#{$comboboxCursor}, pointer);
      width: var(#{iconVars.$iconSize});
      height: var(#{iconVars.$iconSize});

      @include mixins.svg-icon($expandIcon, $expandIconWidth $expandIconHeight);
      background-color: tokens.$bm-comp-input-color-icon;
      inset-inline-end: calc(
        var(#{inputVars.$fieldPaddingX}) -
          (var(#{iconVars.$iconSize}) - $expandIconWidth) / 2
      );
      inset-block-start: calc(
        var(#{inputVars.$fieldHeight}) / 2 - var(#{iconVars.$iconSize}) / 2
      );

      transition: transform 0.2s ease;

      .#{$comboboxBaseClass}--dropdown-open & {
        transform: rotate(180deg)
          translateY(tokens.$bm-comp-input-border-width-field-default);
      }
    }

    &__before,
    &__chips,
    &__input,
    &__after {
      display: flex;
      align-items: center;
      flex: 0 0 auto;
      gap: tokens.$bm-comp-input-space-field-gap;
      min-height: calc(
        var(#{inputVars.$fieldHeight}) - 2 *
          tokens.$bm-comp-input-border-width-field-default - 2 *
          var(#{inputVars.$fieldPaddingY})
      );
      line-height: calc(
        var(#{inputVars.$fieldHeight}) - 2 *
          tokens.$bm-comp-input-border-width-field-default - 2 *
          var(#{inputVars.$fieldPaddingY})
      );
    }

    &__input {
      background: transparent;
      min-height: calc(
        var(#{inputVars.$fieldHeight}) - 2 * var(#{inputVars.$fieldPaddingY})
      );
      line-height: calc(
        var(#{inputVars.$fieldHeight}) - 2 * var(#{inputVars.$fieldPaddingY})
      );

      &::placeholder {
        color: tokens.$bm-comp-input-color-text-placeholder;
      }
    }

    &__content-before,
    &__content-after {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: tokens.$bm-comp-input-space-field-gap;
      color: tokens.$bm-comp-input-color-text-placeholder;
    }

    &__content-before,
    &__content-after {
      display: flex;
      align-items: center;
      justify-content: center;
      gap: tokens.$bm-comp-input-space-field-gap;
      color: tokens.$bm-comp-input-color-text-placeholder;
    }

    &__chips {
      flex: 1;
      gap: tokens.$bm-sem-space-25;
      flex-wrap: wrap;
      margin-block: calc(-1 * tokens.$bm-comp-input-border-width-field-default);
    }

    // Beam icons in the content slots resize with the field; chips and the
    // chevron are unaffected, per EPTOOLS-1515.
    &__content-before,
    &__content-after {
      svg,
      ::slotted([slot*='content']) {
        color: tokens.$bm-comp-input-color-icon;
        height: tokens.$bm-sem-size-icon-sm;
      }

      @include inputVars.field-content-icon;
    }

    &__input {
      flex: 1;
      cursor: var(#{$comboboxInputCursor}, pointer);

      text-overflow: ellipsis;

      border: 0;
      outline: 0;
      margin: 0;
      padding: 0;
      font: var(#{inputVars.$fieldFont});

      width: 100%;
      min-width: 3rem;
    }
  }

  @each $state, $styleTokens in $stateStyleTokens {
    &--#{$state} &__field__chevron {
      background-color: map.get($styleTokens, expandIconColor);
    }

    &--#{$state} &__field {
      color: map.get($styleTokens, textColor);
      border-color: map.get($styleTokens, borderColor);
      background-color: map.get($styleTokens, backgroundColor);

      @if ($state == error) {
        @include mixins.simulated-inset-outline(
          tokens.$bm-comp-input-border-width-field-error,
          solid,
          map.get($styleTokens, borderColor),
          calc(0px - #{tokens.$bm-comp-input-border-width-field-error})
        );
      }
    }
  }

  &--disabled &__field &__field__input {
    color: tokens.$bm-comp-input-color-text-disabled;

    &::placeholder {
      color: tokens.$bm-comp-input-color-text-disabled;
    }
  }

  &__field {
    border: tokens.$bm-comp-input-border-width-field-default solid
      tokens.$bm-comp-input-color-border;
    border-radius: tokens.$bm-comp-input-radius-field;

    cursor: var(#{$comboboxInputCursor}, pointer);
    box-shadow: tokens.$bm-comp-input-shadow-field;
    background-color: tokens.$bm-comp-input-color-bg;
    transform: translate3d(
      tokens.$bm-sem-space-0,
      tokens.$bm-sem-space-0,
      tokens.$bm-sem-space-0
    );

    padding-block: var(#{inputVars.$fieldPaddingY});
    padding-inline: var(#{inputVars.$fieldPaddingX})
      calc(
        #{$expandIconWidth} + #{tokens.$bm-comp-input-space-field-gap} +
          var(#{inputVars.$fieldPaddingX})
      );

    min-height: var(#{inputVars.$fieldHeight});

    &:focus-within {
      @include mixins.simulated-inset-outline(
        tokens.$bm-sem-border-width-focus,
        solid,
        tokens.$bm-sem-color-border-focus,
        calc(0px - #{tokens.$bm-sem-size-focus-offset})
      );
    }
  }

  &__dropdown {
    padding: tokens.$bm-sem-space-50 tokens.$bm-sem-space-100 !important;

    // Calculate max-height based on the max number of items and item height, plus padding.
    // This exact calculation is also applied in the JS to set the max-height style on the
    // dropdown or the available space below the input, whichever is smaller. We keep this
    // here in CSS to ensure that the styles are applied on the first render before JS can
    // set the max-height, to prevent a flash of an overly tall dropdown
    max-height: calc(
      var(#{$comboboxDropdownMaxItemsVar}, 8) * #{tokens.$bm-comp-actionlist-size-height} +
        2 * #{tokens.$bm-sem-space-50}
    );
    overflow-y: auto;
  }
}
