@use './animation' as animation;

%after-before {
  position: absolute;
  top: 0;
  left: 0;
  z-index: var(--neo-z-index-behind, -1);
  display: flex;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  opacity: 0;
  content: '';
}

@mixin pulse(
  $box-shadow: var(--neo-pulse-box-shadow, var(--neo-box-shadow-raised-3)),
  $box-shadow-reverse: var(--neo-pulse-box-shadow-reverse, var(--neo-box-shadow-inset-2)),
  $duration: var(--neo-pulse-duration, 6s),
  $delay: var(--neo-pulse-delay, 1s),
  $interval: var(--neo-pulse-interval, 3s),
  $iteration: infinite,
  $scaleX: var(--neo-pulse-scale-x, 2),
  $scaleY: var(--neo-pulse-scale-y, 2),
  $opacity-start: 1,
  $opacity-end: 0,
  $reverse: false
) {
  position: relative;

  &::after,
  &::before {
    @extend %after-before;

    box-shadow: $box-shadow;
    will-change: transform, opacity;
  }

  &::before {
    animation: pulse $duration linear $delay $iteration;
  }

  &::after {
    animation: pulse $duration linear calc(#{$delay} + #{$interval}) $iteration;
  }

  @if $reverse {
    &.neo-pressed,
    &:active {
      &::after,
      &::before {
        box-shadow: $box-shadow-reverse;
        animation-name: coalesce;
        animation-timing-function: ease-out;
      }
    }

    @include animation.coalesce($scaleX, $scaleY, $opacity-start, $opacity-end);
  }

  @include animation.pulse($scaleX, $scaleY, $opacity-start, $opacity-end);
}

@mixin coalesce(
  $box-shadow: var(--neo-box-shadow-raised-3),
  $box-shadow-reverse: var(--neo-box-shadow-inset-2),
  $duration: var(--neo-coalesce-duration, 6s),
  $delay: var(--neo-coalesce-delay, 1s),
  $interval: var(--neo-coalesce-interval, 3s),
  $iteration: infinite,
  $scaleX: var(--neo-coalesce-scale-x, 2),
  $scaleY: var(--neo-coalesce-scale-y, 2),
  $opacity-start: 1,
  $opacity-end: 0,
  $reverse: false
) {
  position: relative;

  &::after,
  &::before {
    @extend %after-before;

    box-shadow: var(--neo-coalesce-box-shadow, #{$box-shadow});
    will-change: transform, opacity;
  }

  &::before {
    animation: coalesce $duration ease-out $delay $iteration;
  }

  &::after {
    animation: coalesce $duration ease-out calc(#{$delay} + #{$interval}) $iteration;
  }

  @if $reverse {
    &.neo-pressed,
    &:active {
      &::after,
      &::before {
        box-shadow: var(--neo-coalesce-box-shadow-reverse, #{$box-shadow-reverse});
        animation-name: pulse;
        animation-timing-function: linear;
      }
    }

    @include animation.pulse($scaleX, $scaleY, $opacity-start, $opacity-end);
  }

  @include animation.coalesce($scaleX, $scaleY, $opacity-start, $opacity-end);
}

@mixin border-rotate(
  $source-color: var(--neo-rotate-source-color, transparent),
  $target-color: var(--neo-rotate-target-color, var(--neo-color-primary-50)),
  $border-width: var(--neo-border-width, 1px),
  $speed: var(--neo-rotate-speed, 4s),
  $easing: var(--neo-rotate-easing, linear)
) {
  position: relative;
  border: $border-width solid transparent;
  border-radius: 2rem;

  &::before {
    position: absolute;
    inset: 0;
    padding: $border-width;
    background: conic-gradient(from var(--neo-angle), #{$source-color} 20%, #{$target-color} 80%);
    border-radius: inherit;
    animation: $speed rotate $easing infinite;
    content: '';
    mask:
      conic-gradient(black 0 0) content-box exclude,
      conic-gradient(black 0 0);
    pointer-events: none;
  }

  &.neo-filled {
    --neo-source-color: var(--neo-target-color);
  }

  &.neo-empty {
    --neo-target-color: transparent;
  }

  @include animation.rotate;
}

@mixin border-progress(
  $border-color: var(--neo-progress-border-color, var(--neo-color-primary-50)),
  $border-width: 1px,
  $transition: --neo-progress,
  $speed: var(--neo-rotate-speed, 4s),
  $easing: var(--neo-rotate-easing, linear)
) {
  position: relative;
  border: $border-width solid transparent;
  border-radius: 2rem;

  &::before {
    position: absolute;
    inset: 0;
    padding: $border-width;
    background: conic-gradient($border-color, $border-color var(--neo-progress), transparent var(--neo-progress));
    border-radius: inherit;
    transition: $transition $speed $easing;
    content: '';
    mask:
      conic-gradient(black 0 0) content-box exclude,
      conic-gradient(black 0 0);
    pointer-events: none;
  }
}

@mixin skeleton(
  $start: 1,
  $step: var(--neo-skeleton-step, -0.3),
  $color: var(--neo-skeleton-color),
  $text: var(--neo-skeleton-color),
  $timing: 3s,
  $easing: var(--neo-transition-skeleton),
  $delay: 1s,
  $content: true
) {
  --neo-skeleton-start: #{$start};
  --neo-skeleton-end: calc(#{$start} + #{$step});

  color: $text;
  background-color: $color;
  background-clip: padding-box;
  border-color: $color;
  opacity: $start;
  transition:
    background-color $delay ease,
    color calc($delay / 3) ease,
    border-color $delay ease,
    opacity $delay ease;
  animation: skeleton $timing $easing infinite;
  animation-delay: $delay;

  @if $content {
    &::before,
    &::after,
    :global(> *::before),
    :global(> *::after),
    :global(> *) {
      visibility: hidden;
      pointer-events: none;
    }
  }

  @include animation.skeleton;
}

@mixin scrollbar(
  $overflow: var(--neo-scrollbar-overflow, auto),
  $gutter: stable both-edges,
  $width: var(--neo-scrollbar-width, 0.375rem),
  $thumb-color: var(--neo-scrollbar-color),
  $thumb-border-radius: var(--neo-border-radius),
  $button-height: var(--neo-scrollbar-button-height, 0.125rem),
  $timing: 0.3s,
  $delay: 0.1s,
  $padding: calc($width * 2),
  $transition: false
) {
  scrollbar-gutter: $gutter;
  overflow: $overflow;

  @if $transition {
    transition:
      $transition,
      --neo-thumb-color calc($timing * 1.5) ease $delay;
  } @else {
    transition: --neo-thumb-color calc($timing * 1.5) ease $delay;
  }

  &:focus-within,
  &:focus,
  &:hover {
    --neo-thumb-color: #{$thumb-color};

    @if $transition {
      transition:
        $transition,
        --neo-thumb-color calc($timing * 1.5) ease 0s;
    } @else {
      transition: --neo-thumb-color calc($timing * 1.5) ease 0s;
    }
  }

  &::-webkit-scrollbar {
    width: $width;
    background-color: transparent;
    border: none;
    cursor: pointer;
  }

  &::-webkit-scrollbar:vertical {
    width: $width;
  }

  &::-webkit-scrollbar:horizontal {
    height: $width;
  }

  &::-webkit-scrollbar-button {
    display: block;

    &:hover {
      background-color: var(--neo-thumb-color, transparent);
    }
  }

  &::-webkit-scrollbar-button:vertical {
    height: $button-height;
  }

  &::-webkit-scrollbar-button:horizontal {
    width: $button-height;
  }

  &::-webkit-scrollbar-thumb {
    background-color: var(--neo-thumb-color, transparent);
    border: none;
    border-radius: $thumb-border-radius;
    cursor: pointer;
  }

  &::-webkit-scrollbar-corner {
    background-color: transparent;
    background-clip: border-box;
    border: none;
    outline: none;
  }

  &::-webkit-resizer {
    background: url('../assets/neo-icon-resizer-bottom-right.svg') no-repeat bottom;
    background-clip: border-box;
  }

  // TODO: remove when Firefox supports scrollbar customization
  @supports not selector(::-webkit-scrollbar) {
    scrollbar-width: thin;
    scrollbar-color: $thumb-color;

    @if $padding != none {
      padding-inline: $padding;
    }
  }

  // TODO: remove when Safari  implement scrollbar-gutter correctly
  @if $padding != none {
    @supports (hanging-punctuation: first) and (font: -apple-system-body) and (-webkit-appearance: none) {
      padding-inline: $padding;
    }
  }
}

@mixin fade-scroll($fade-height: 1rem, $direction: top) {
  mask-image: linear-gradient(
    to var(--neo-scroll-direction, #{$direction}),
    black,
    black,
    transparent 0,
    black var(--neo-scroll-shadow-size, #{$fade-height}),
    black calc(100% - var(--neo-scroll-shadow-size, #{$fade-height})),
    transparent
  );
}

@mixin glass() {
  /** Box Shadows raised */
  --neo-box-shadow-raised-5: var(--neo-glass-box-shadow-raised-5);
  --neo-box-shadow-raised-4: var(--neo-glass-box-shadow-raised-4);
  --neo-box-shadow-raised-3: var(--neo-glass-box-shadow-raised-3);
  --neo-box-shadow-raised-2: var(--neo-glass-box-shadow-raised-2);
  --neo-box-shadow-raised-1: var(--neo-glass-box-shadow-raised-1);

  /** Box Shadows inset */
  --neo-box-shadow-inset-1: var(--neo-glass-box-shadow-inset-1);
  --neo-box-shadow-inset-2: var(--neo-glass-box-shadow-inset-2);
  --neo-box-shadow-inset-3: var(--neo-glass-box-shadow-inset-3);
  --neo-box-shadow-inset-4: var(--neo-glass-box-shadow-inset-4);
  --neo-box-shadow-inset-5: var(--neo-glass-box-shadow-inset-5);

  /** Box Shadows pressed */
  --neo-box-shadow-pressed-1: var(--neo-glass-box-shadow-pressed-1);
  --neo-box-shadow-pressed-2: var(--neo-glass-box-shadow-pressed-2);
  --neo-box-shadow-pressed-3: var(--neo-glass-box-shadow-pressed-3);
  --neo-box-shadow-pressed-4: var(--neo-glass-box-shadow-pressed-4);
  --neo-box-shadow-pressed-5: var(--neo-glass-box-shadow-pressed-5);

  /** Box Shadows convex */
  --neo-box-shadow-convex-1: var(--neo-glass-box-shadow-convex-1);
  --neo-box-shadow-convex-2: var(--neo-glass-box-shadow-convex-2);
  --neo-box-shadow-convex-3: var(--neo-glass-box-shadow-convex-3);
  --neo-box-shadow-convex-4: var(--neo-glass-box-shadow-convex-4);
  --neo-box-shadow-convex-5: var(--neo-glass-box-shadow-convex-5);

  /** Skeleton color */
  --neo-skeleton-color: var(--neo-glass-skeleton-color);
}

@mixin floating(
  $padding: --neo-tooltip-padding,
  $background-color: --neo-tooltip-bg-color,
  $border-color: --neo-tooltip-border-color,
  $border-radius: --neo-tooltip-border-radius,
  $box-shadow: --neo-tooltip-box-shadow,
  $backdrop-filter: --neo-tooltip-backdrop-filter,
  $z-index: --neo-tooltip-z-index
) {
  z-index: var($z-index, var(--neo-z-index-layer-ui, 1000));
  padding: var($padding, 0.4375rem 0.625rem);
  background-color: var($background-color, var(--neo-glass-background-color));
  border: var(--neo-border-width, 1px) solid var($border-color, var(--neo-glass-background-color));
  border-color: var(
    $border-color,
    var(--neo-glass-top-border-color) var(--neo-glass-right-border-color) var(--neo-glass-bottom-border-color) var(--neo-glass-left-border-color)
  );
  border-radius: var($border-radius, var(--neo-border-radius));
  outline: none;
  box-shadow: var($box-shadow, var(--neo-glass-box-shadow-raised-1));
  backdrop-filter: var($backdrop-filter, var(--neo-blur-3));
  transition:
    box-shadow 0.3s ease,
    backdrop-filter 0.3s ease,
    border-radius 0.3s ease,
    border-color 0.3s ease,
    padding 0.3s ease;
}

@mixin ellipsis($line: var(--neo-ellipsis-lines, 1), $word-break: break-word) {
  display: -webkit-box;
  -webkit-line-clamp: $line;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  word-break: $word-break;
}

@mixin transition-container($area: transition, $width: 100%) {
  display: grid;
  flex-grow: 1;
  grid-template-areas: '#{$area}';
  width: $width;

  :global(> *) {
    grid-area: $area;
  }
}
