@use '@angular/cdk';
@use '../core/style/vendor-prefixes';
@use '../core/tokens/token-utils';
@use '../core/tokens/m2/mdc/filled-text-field' as tokens-mdc-filled-text-field;
@use '../core/tokens/m2/mdc/outlined-text-field' as tokens-mdc-outlined-text-field;

// Includes the structural styles for the form field inherited from MDC.
@mixin private-text-field-structure {
  $filled-slots: (
    tokens-mdc-filled-text-field.$prefix,
    tokens-mdc-filled-text-field.get-token-slots()
  );
  $outlined-slots: (
    tokens-mdc-outlined-text-field.$prefix,
    tokens-mdc-outlined-text-field.get-token-slots()
  );

  .mdc-text-field {
    display: inline-flex;
    align-items: baseline;
    padding: 0 16px;
    position: relative;
    box-sizing: border-box;
    overflow: hidden;
    will-change: opacity, transform, color;

    // TODO(crisbeto): The filled form field overrides these while the outlined doesn't.
    // The correct thing to do would be to remove them from here and have the one based on the
    // token in the outlined appearance. We keep them as is for now to avoid screenshot diffs.
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;
  }

  .mdc-text-field__input {
    width: 100%;
    min-width: 0;
    border: none;
    border-radius: 0;
    background: none;
    padding: 0;
    -moz-appearance: none;
    -webkit-appearance: none;

    // TODO(crisbeto): this height gets overwritten eventually, but there are some internal
    // tests that depend on this being here in weird ways so we're keeping it around for now.
    height: 28px;

    // Note that while this style and the `-ms-clear` are identical, we can't combine
    // them because if one of them isn't supported, it'll invalidate the whole rule.
    &::-webkit-calendar-picker-indicator {
      display: none;
    }

    &::-ms-clear {
      display: none;
    }

    &:focus {
      outline: none;
    }

    &:invalid {
      box-shadow: none;
    }

    @include vendor-prefixes.input-placeholder {
      opacity: 0;
    }

    .mdc-text-field--no-label &,
    .mdc-text-field--focused & {
      @include vendor-prefixes.input-placeholder {
        opacity: 1;
      }
    }

    .mdc-text-field--disabled:not(.mdc-text-field--no-label) &.mat-mdc-input-disabled-interactive {
      @include vendor-prefixes.input-placeholder {
        opacity: 0;
      }
    }

    .mdc-text-field--outlined &,
    .mdc-text-field--filled.mdc-text-field--no-label & {
      height: 100%;
    }

    .mdc-text-field--outlined & {
      display: flex;
      border: none !important;
      background-color: transparent;
    }

    .mdc-text-field--disabled & {
      pointer-events: auto;
    }

    @include token-utils.use-tokens($filled-slots...) {
      @include _input-tokens('.mdc-text-field--filled');
    }

    @include token-utils.use-tokens($outlined-slots...) {
      @include _input-tokens('.mdc-text-field--outlined');
    }

    @include cdk.high-contrast {
      .mdc-text-field--disabled & {
        background-color: Window;
      }
    }
  }

  .mdc-text-field--filled {
    height: 56px;
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;

    @include token-utils.use-tokens($filled-slots...) {
      @include token-utils.create-token-slot(border-top-left-radius, container-shape);
      @include token-utils.create-token-slot(border-top-right-radius, container-shape);

      &:not(.mdc-text-field--disabled) {
        @include token-utils.create-token-slot(background-color, container-color);
      }

      &.mdc-text-field--disabled {
        @include token-utils.create-token-slot(background-color, disabled-container-color);
      }
    }
  }

  .mdc-text-field--outlined {
    height: 56px;
    overflow: visible;

    @include token-utils.use-tokens($outlined-slots...) {
      $shape-var: token-utils.get-token-variable(container-shape);
      padding-right: max(16px, #{$shape-var});
      padding-left: max(16px, calc(#{$shape-var} + 4px));

      [dir='rtl'] & {
        padding-right: max(16px, calc(#{$shape-var} + 4px));
        padding-left: max(16px, #{$shape-var});
      }
    }
  }

  .mdc-floating-label {
    position: absolute;
    left: 0;
    transform-origin: left top;
    line-height: 1.15rem;
    text-align: left;
    text-overflow: ellipsis;
    white-space: nowrap;
    cursor: text;
    overflow: hidden;
    will-change: transform;

    [dir='rtl'] & {
      right: 0;
      left: auto;
      transform-origin: right top;
      text-align: right;
    }

    .mdc-text-field & {
      top: 50%;
      transform: translateY(-50%);
      pointer-events: none;
    }

    .mdc-notched-outline & {
      display: inline-block;
      position: relative;
      max-width: 100%;
    }

    .mdc-text-field--outlined & {
      left: 4px;
      right: auto;
    }

    [dir='rtl'] .mdc-text-field--outlined & {
      left: auto;
      right: 4px;
    }

    .mdc-text-field--filled & {
      left: 16px;
      right: auto;
    }

    [dir='rtl'] .mdc-text-field--filled & {
      left: auto;
      right: 16px;
    }

    .mdc-text-field--disabled & {
      cursor: default;

      @include cdk.high-contrast {
        z-index: 1;
      }
    }

    .mdc-text-field--filled.mdc-text-field--no-label & {
      display: none;
    }

    @include token-utils.use-tokens($filled-slots...) {
      @include _floating-label-tokens('.mdc-text-field--filled');
    }

    @include token-utils.use-tokens($outlined-slots...) {
      @include _floating-label-tokens('.mdc-text-field--outlined');
    }
  }

  .mdc-floating-label--float-above {
    cursor: auto;
    transform: translateY(-106%) scale(0.75);

    .mdc-text-field--filled & {
      transform: translateY(-106%) scale(0.75);
    }

    .mdc-text-field--outlined & {
      transform: translateY(-37.25px) scale(1);
      font-size: 0.75rem;
    }

    .mdc-notched-outline & {
      text-overflow: clip;
    }

    .mdc-notched-outline--upgraded & {
      max-width: 133.3333333333%;
    }

    .mdc-text-field--outlined.mdc-notched-outline--upgraded &,
    .mdc-text-field--outlined .mdc-notched-outline--upgraded & {
      transform: translateY(-34.75px) scale(0.75);
    }

    .mdc-text-field--outlined.mdc-notched-outline--upgraded &,
    .mdc-text-field--outlined .mdc-notched-outline--upgraded & {
      font-size: 1rem;
    }
  }

  .mdc-floating-label--required {
    &:not(.mdc-floating-label--hide-required-marker)::after {
      margin-left: 1px;
      margin-right: 0;
      content: '*';

      [dir='rtl'] & {
        margin-left: 0;
        margin-right: 1px;
      }
    }
  }

  .mdc-notched-outline {
    display: flex;
    position: absolute;
    top: 0;
    right: 0;
    left: 0;
    box-sizing: border-box;
    width: 100%;
    max-width: 100%;
    height: 100%;
    text-align: left;
    pointer-events: none;

    [dir='rtl'] & {
      text-align: right;
    }

    .mdc-text-field--outlined & {
      z-index: 1;
    }
  }

  .mat-mdc-notch-piece {
    box-sizing: border-box;
    height: 100%;
    pointer-events: none;
    border-top: 1px solid;
    border-bottom: 1px solid;

    .mdc-text-field--focused & {
      border-width: 2px;
    }

    @include token-utils.use-tokens($outlined-slots...) {
      // Moved out into variables because the selectors we inherited were too long.
      $enabled-selector: '.mdc-text-field--outlined:not(.mdc-text-field--disabled)';
      $hover-selector: ':not(.mdc-text-field--focused):hover';

      #{$enabled-selector} & {
        @include token-utils.create-token-slot(border-color, outline-color);
        @include token-utils.create-token-slot(border-width, outline-width);
      }

      #{$enabled-selector}#{$hover-selector} & {
        @include token-utils.create-token-slot(border-color, hover-outline-color);
      }

      #{$enabled-selector}.mdc-text-field--focused & {
        @include token-utils.create-token-slot(border-color, focus-outline-color);
      }

      .mdc-text-field--outlined.mdc-text-field--disabled & {
        @include token-utils.create-token-slot(border-color, disabled-outline-color);
      }

      #{$enabled-selector}.mdc-text-field--invalid & {
        @include token-utils.create-token-slot(border-color, error-outline-color);
      }

      #{$enabled-selector}.mdc-text-field--invalid#{$hover-selector} .mdc-notched-outline & {
        @include token-utils.create-token-slot(border-color, error-hover-outline-color);
      }

      #{$enabled-selector}.mdc-text-field--invalid.mdc-text-field--focused & {
        @include token-utils.create-token-slot(border-color, error-focus-outline-color);
      }

      #{$enabled-selector}.mdc-text-field--focused .mdc-notched-outline & {
        @include token-utils.create-token-slot(border-width, focus-outline-width);
      }
    }
  }

  .mdc-notched-outline__leading {
    border-left: 1px solid;
    border-right: none;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;

    @include token-utils.use-tokens($outlined-slots...) {
      @include token-utils.create-token-slot(border-top-left-radius, container-shape);
      @include token-utils.create-token-slot(border-bottom-left-radius, container-shape);

      .mdc-text-field--outlined .mdc-notched-outline & {
        $shape-var: token-utils.get-token-variable(container-shape);
        width: max(12px, #{$shape-var});
      }
    }

    [dir='rtl'] & {
      border-left: none;
      border-right: 1px solid;
      border-bottom-left-radius: 0;
      border-top-left-radius: 0;

      @include token-utils.use-tokens($outlined-slots...) {
        @include token-utils.create-token-slot(border-top-right-radius, container-shape);
        @include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
      }
    }
  }

  .mdc-notched-outline__trailing {
    flex-grow: 1;
    border-left: none;
    border-right: 1px solid;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;

    @include token-utils.use-tokens($outlined-slots...) {
      @include token-utils.create-token-slot(border-top-right-radius, container-shape);
      @include token-utils.create-token-slot(border-bottom-right-radius, container-shape);
    }

    [dir='rtl'] & {
      border-left: 1px solid;
      border-right: none;
      border-top-right-radius: 0;
      border-bottom-right-radius: 0;

      @include token-utils.use-tokens($outlined-slots...) {
        @include token-utils.create-token-slot(border-top-left-radius, container-shape);
        @include token-utils.create-token-slot(border-bottom-left-radius, container-shape);
      }
    }
  }

  .mdc-notched-outline__notch {
    flex: 0 0 auto;
    width: auto;

    @include token-utils.use-tokens($outlined-slots...) {
      .mdc-text-field--outlined .mdc-notched-outline & {
        $shape-var: token-utils.get-token-variable(container-shape);
        max-width: min(
          var(--mat-form-field-notch-max-width, 100%),
          calc(100% - max(12px, #{$shape-var}) * 2)
        );
      }
    }

    .mdc-text-field--outlined .mdc-notched-outline--notched & {
      padding-top: 1px;
    }

    .mdc-text-field--focused.mdc-text-field--outlined .mdc-notched-outline--notched & {
      padding-top: 2px;
    }

    .mdc-notched-outline--notched & {
      padding-left: 0;
      padding-right: 8px;
      border-top: none;
      --mat-form-field-notch-max-width: 100%;
    }

    [dir='rtl'] .mdc-notched-outline--notched & {
      padding-left: 8px;
      padding-right: 0;
    }

    .mdc-notched-outline--no-label & {
      display: none;
    }
  }

  .mdc-line-ripple {
    &::before,
    &::after {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      border-bottom-style: solid;
      content: '';
    }

    &::before {
      z-index: 1;

      @include token-utils.use-tokens($filled-slots...) {
        $enabled-field: '.mdc-text-field--filled:not(.mdc-text-field--disabled)';

        @include token-utils.create-token-slot(border-bottom-width, active-indicator-height);

        #{$enabled-field} & {
          @include token-utils.create-token-slot(border-bottom-color, active-indicator-color);
        }

        #{$enabled-field}:not(.mdc-text-field--focused):hover & {
          @include token-utils.create-token-slot(border-bottom-color, hover-active-indicator-color);
        }

        .mdc-text-field--filled.mdc-text-field--disabled & {
          @include token-utils.create-token-slot(
            border-bottom-color,
            disabled-active-indicator-color
          );
        }

        #{$enabled-field}.mdc-text-field--invalid & {
          @include token-utils.create-token-slot(border-bottom-color, error-active-indicator-color);
        }

        #{$enabled-field}.mdc-text-field--invalid:not(.mdc-text-field--focused):hover & {
          @include token-utils.create-token-slot(
            border-bottom-color,
            error-hover-active-indicator-color
          );
        }
      }
    }

    &::after {
      transform: scaleX(0);
      opacity: 0;
      z-index: 2;

      @include token-utils.use-tokens($filled-slots...) {
        .mdc-text-field--filled & {
          @include token-utils.create-token-slot(
            border-bottom-width,
            focus-active-indicator-height
          );
        }

        .mdc-text-field--filled:not(.mdc-text-field--disabled) & {
          @include token-utils.create-token-slot(border-bottom-color, focus-active-indicator-color);
        }

        .mdc-text-field--filled.mdc-text-field--invalid:not(.mdc-text-field--disabled) & {
          @include token-utils.create-token-slot(
            border-bottom-color,
            error-focus-active-indicator-color
          );
        }
      }
    }
  }

  .mdc-line-ripple--active::after {
    transform: scaleX(1);
    opacity: 1;
  }

  .mdc-line-ripple--deactivating::after {
    opacity: 0;
  }

  .mdc-text-field--disabled {
    pointer-events: none;
  }
}

// Includes the tokens for the floating label for a specific form field variant.
@mixin _floating-label-tokens($selector) {
  $enabled-field: '#{$selector}:not(.mdc-text-field--disabled)';

  #{$enabled-field} & {
    @include token-utils.create-token-slot(color, label-text-color);
  }

  #{$enabled-field}.mdc-text-field--focused & {
    @include token-utils.create-token-slot(color, focus-label-text-color);
  }

  #{$enabled-field}:not(.mdc-text-field--focused):hover & {
    @include token-utils.create-token-slot(color, hover-label-text-color);
  }

  #{$selector}.mdc-text-field--disabled & {
    @include token-utils.create-token-slot(color, disabled-label-text-color);
  }

  #{$enabled-field}.mdc-text-field--invalid & {
    @include token-utils.create-token-slot(color, error-label-text-color);
  }

  #{$enabled-field}.mdc-text-field--invalid.mdc-text-field--focused & {
    @include token-utils.create-token-slot(color, error-focus-label-text-color);
  }

  #{$enabled-field}.mdc-text-field--invalid:not(.mdc-text-field--disabled):hover & {
    @include token-utils.create-token-slot(color, error-hover-label-text-color);
  }

  #{$selector} & {
    @include token-utils.create-token-slot(font-family, label-text-font);
    @include token-utils.create-token-slot(font-size, label-text-size);
    @include token-utils.create-token-slot(font-weight, label-text-weight);
    @include token-utils.create-token-slot(letter-spacing, label-text-tracking);
  }
}

// Includes the tokens for the input for a specific form field variant.
@mixin _input-tokens($selector) {
  #{$selector}:not(.mdc-text-field--disabled) & {
    @include token-utils.create-token-slot(color, input-text-color);
    @include token-utils.create-token-slot(caret-color, caret-color);

    @include vendor-prefixes.input-placeholder {
      @include token-utils.create-token-slot(color, input-text-placeholder-color);
    }
  }

  #{$selector}.mdc-text-field--invalid:not(.mdc-text-field--disabled) & {
    @include token-utils.create-token-slot(caret-color, error-caret-color);
  }

  #{$selector}.mdc-text-field--disabled & {
    @include token-utils.create-token-slot(color, disabled-input-text-color);
  }
}

// Includes the animation styles for the form field inherited from MDC.
@mixin private-text-field-animations {
  $timing-curve: cubic-bezier(0.4, 0, 0.2, 1);

  .mdc-floating-label {
    transition:
      transform 150ms $timing-curve,
      color 150ms $timing-curve;
  }

  .mdc-text-field__input {
    transition: opacity 150ms $timing-curve;

    @include vendor-prefixes.input-placeholder {
      transition: opacity 67ms $timing-curve;
    }
  }

  &.mdc-text-field--no-label,
  &.mdc-text-field--focused {
    .mdc-text-field__input {
      @include vendor-prefixes.input-placeholder {
        transition-delay: 40ms;
        transition-duration: 110ms;
      }
    }
  }

  .mdc-text-field--filled:not(.mdc-ripple-upgraded):focus .mdc-text-field__ripple::before {
    transition-duration: 75ms;
  }

  .mdc-line-ripple::after {
    transition: transform 180ms $timing-curve, opacity 180ms $timing-curve;
  }

  .mat-mdc-form-field-hint-wrapper,
  .mat-mdc-form-field-error-wrapper {
    animation-duration: 300ms;
  }
}
