/*
 * Utilities
 */

@use 'sass:map';
@use 'sass:string';

@use '../../components/space/style/space-mixins.scss' as space-mixins;
@forward '../../components/space/style/space-mixins.scss';

@mixin defaultDropShadow() {
  box-shadow: var(--shadow-default);
}

@mixin sharpDropShadow() {
  box-shadow: var(--shadow-sharp);
}

// Uses html:not([data-whatintent='touch'] )
// classes on <html> element
// based on js touch device test
@mixin hover() {
  html:not([data-whatintent='touch']) &:hover {
    &[disabled] {
      cursor: not-allowed;
    }
    &:not([disabled]) {
      @content;
    }
  }
}
@mixin active() {
  &:active,
  html:not([data-whatintent='touch']) &:active {
    &[disabled] {
      cursor: not-allowed;
    }
    // stylelint-disable-next-line
    &:not([disabled]) {
      @content;
    }
  }
}

@mixin focusVisible() {
  &:focus-visible {
    @include whatInputNot('touch') {
      &[disabled] {
        cursor: not-allowed;
      }
      // stylelint-disable-next-line
      &:not([disabled]) {
        @content;
      }
    }
  }
}

@mixin focus() {
  &:focus {
    &[disabled] {
      cursor: not-allowed;
    }
    // stylelint-disable-next-line
    &:not([disabled]) {
      @content;
    }
  }
}

@mixin reducedMotion() {
  @media (prefers-reduced-motion: reduce) {
    @content;
  }
}

@mixin whatInput($whatinput: null) {
  html[data-whatinput='#{$whatinput}'] & {
    @content;
  }
}
@mixin whatInputNot($whatinput: null) {
  html:not([data-whatinput='#{$whatinput}']) & {
    @content;
  }
}

@mixin focusStyle(
  $bgColor: var(--token-color-background-action-focus-subtle),
  $textColor: var(--token-color-text-neutral-inverse),
  $borderColor: var(--token-color-stroke-action-focus),
  $borderWidth: var(--focus-ring-width),
  $inset: null,
  $extendShadow: null,
  $outline: none
) {
  outline: $outline;
  background-color: $bgColor;
  color: $textColor;

  @if $borderColor != null {
    @include fakeBorder(
      $borderColor,
      $borderWidth,
      $inset,
      $extendShadow: $extendShadow
    );
  }
}

@mixin focusRing(
  $whatinput: null,
  $color: null,
  $borderWidth: null,
  $inset: null,
  $extendShadow: null
) {
  outline: none;

  @if $whatinput == null {
    $whatinput: 'keyboard';
  }
  @if $color == null {
    $color: var(--token-color-stroke-action-focus);
  }
  @if $borderWidth == null {
    $borderWidth: var(--focus-ring-width);
  }

  @if $whatinput == 'always' {
    @include focusStyle(
      $bgColor: null,
      $textColor: null,
      $borderColor: $color,
      $borderWidth: $borderWidth,
      $inset: $inset,
      $extendShadow: $extendShadow,
      $outline: null
    );
  } @else {
    @include whatInput($whatinput) {
      @include focusStyle(
        $bgColor: null,
        $textColor: null,
        $borderColor: $color,
        $borderWidth: $borderWidth,
        $inset: $inset,
        $extendShadow: $extendShadow,
        $outline: null
      );
    }
  }
}

@mixin removeFocusRing($whatinput: null, $replace: none) {
  outline: initial;

  @if $whatinput == null {
    box-shadow: $replace;
  }

  html[data-whatinput='#{$whatinput}'] & {
    box-shadow: $replace;
  }
}

@mixin fakeBorder(
  $color: null,
  $width: null /* 1px */,
  $inset: null,
  $important: null,
  $extendShadow: null
) {
  @if $width == null {
    $width: 0.0625rem;
  }

  --border-color: #{$color};
  --border-width: #{$width};

  // we use !important, cause we have no changes to select the selector right
  // in some cases we have another state where we use box-shadow
  // but with important, we take care of that we actually can use it
  box-shadow: (
      $inset 0 0 0 var(--border-width) var(--border-color),
      $extendShadow
    )
    $important;

  @if $color != null {
    border-color: transparent;
  }
}

@mixin dummySpacing() {
  // we use "aria-hidden" SPAN to simulate a wider width for each tab
  .dnb-dummy {
    display: flex;
    flex-direction: column;

    height: 0;
    visibility: hidden;
    overflow: hidden;
  }
}

@mixin scrollbarAppearance() {
  // NB: We have used "scrollbar-track-width: auto;" before,
  // first, it only effects Firefox.
  // But "thin" changes the behavior in Windows,
  // so it has no arrow buttons, and a weird "pressed" color.
  // Also, on macOS, it changes the scrollbar to be so small,
  // that e.g. the textarea resize grabber gets way smaller.

  scrollbar-color: var(--scrollbar-thumb-color, #888) transparent;

  @supports not (scrollbar-color: auto) {
    // stylelint-disable
    &::-webkit-scrollbar {
      &:vertical {
        width: var(--scrollbar-track-width, 0.5rem);
      }
      &:horizontal {
        height: var(--scrollbar-track-width, 0.5rem);
      }

      border-radius: var(--scrollbar-thumb-width, 0.5rem);
      background-color: var(--scrollbar-track-color, #eee);
    }
    &::-webkit-scrollbar-thumb {
      background-color: var(--scrollbar-thumb-color, #888);

      &:hover {
        background-color: var(--scrollbar-thumb-hover-color, #666);
      }

      border-radius: var(--scrollbar-thumb-width, 0.5rem);
    }
    // stylelint-enable
  }
}

@mixin scrollY($mode: scroll) {
  overflow-y: $mode;
  overscroll-behavior: contain;

  html:not([data-visual-test]) & {
    scroll-behavior: smooth;

    @media (prefers-reduced-motion: reduce) {
      scroll-behavior: auto;
    }
  }

  @include scrollbarAppearance();
}

@mixin scrollX($mode: scroll) {
  overflow-x: $mode;

  @media (prefers-reduced-motion: reduce) {
    scroll-behavior: auto;
  }
  overscroll-behavior: contain;

  html:not([data-visual-test]) & {
    scroll-behavior: smooth;
  }

  @include scrollbarAppearance();
}

@mixin hideScrollbar() {
  /* Hide scrollbar for Chrome, Safari */
  /* stylelint-disable-next-line */
  &::-webkit-scrollbar {
    display: none;
  }
  scrollbar-width: none; /* Firefox */
}

// Firefox fix
@mixin isFirefox() {
  @supports (-moz-appearance: none) {
    @content;
  }
}

// Chrome fix
@mixin isChrome() {
  @supports (-webkit-appearance: none) and
    (not (overflow: -webkit-marquee)) and (not (-moz-appearance: none)) {
    @content;
  }
}

// Safari Mobile fix
@mixin isSafariMobile() {
  @supports (-webkit-touch-callout: none) {
    @content;
  }
}

// Safari Desktop fix
@mixin isSafariDesktop() {
  @supports (-webkit-appearance: none) and (stroke-color: transparent) and
    (not (-webkit-touch-callout: none)) {
    @content;
  }
}

$breakpoints: (
  'xx-small': 15em /* not documented yet */,
  'x-small': 25em /* not documented yet */,
  'small': 40em,
  'medium': 60em,
  'large': 72em,
  'x-large': 80em /* not documented yet */,
  'xx-large': 90em /* not documented yet */,
);
$breakpoint-offset: 0;

@function breakpoint-value($size, $list) {
  @if map.has-key($list, $size) {
    @return map.get($list, $size);
  }

  @return $size;
}

// Example usage:
// @include allAbove(medium){ styles go here.. }
// $offset and $list are needed to provide global customization options
@mixin allAbove($size, $offset: $breakpoint-offset, $list: $breakpoints) {
  @media screen and (min-width: (breakpoint-value($size, $list) + $offset + 0.00625)) {
    @content;
  }
}
@mixin allBelow($size, $offset: $breakpoint-offset, $list: $breakpoints) {
  @media screen and (max-width: (breakpoint-value($size, $list) + $offset)) {
    @content;
  }
}
@mixin allBetween(
  $fromSize,
  $toSize,
  $fromOffset: $breakpoint-offset,
  $toOffset: $breakpoint-offset
) {
  @include allBelow($toSize, $toOffset) {
    @include allAbove($fromSize, $fromOffset) {
      @content;
    }
  }
}

// Vertical alignment helper
@mixin alignmentHelper() {
  // Add a char to align the component
  &::before {
    content: '\2060'; // zero-width non-breaking space
    @include alignmentHelperClass();

    // For supporting HTML v4 (limited-quirks)
    height: 100%;

    opacity: 0; // hide the element in case ISO-8859-1 encoding is used
  }
}
@mixin alignmentHelperClass() {
  display: inline-block;
  width: 0;
  height: 0;

  font-size: var(--font-size-small);

  speak: none;
}

// Screen reader only helper
@mixin srOnly() {
  user-select: none !important;
  -webkit-touch-callout: none !important; // iOS
  pointer-events: none !important;

  position: absolute !important;

  clip-path: inset(50%) !important;
  max-width: 1px !important; // if less than 1px, Safari moves the focus-ring to another place
  max-height: 1px !important; // if less than 1px, Safari moves the focus-ring to another place

  overflow: hidden !important;
  white-space: nowrap !important; // NB: so NVDA not splits up text in multi line

  padding: 0 !important;
  margin: 0 !important;

  border: 0 !important;
}

@function str-replace($string, $search, $replace: '') {
  $index: string.index($string, $search);

  @if $index {
    @return string.slice($string, 1, $index - 1) + $replace +
      str-replace(
        string.slice($string, $index + string.length($search)),
        $search,
        $replace
      );
  }

  @return $string;
}

@mixin formLabelWrap() {
  @media screen and (max-width: 40em) {
    flex-wrap: wrap;
    & > .dnb-form-label {
      margin-bottom: 0.5rem;
      margin-top: 0.5rem;
    }
  }
}

@mixin fieldsetReset() {
  @include space-mixins.spaceReset();
  padding: 0;
  border: none;
}
