// Copyright 2015 Palantir Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0.

@use "sass:math";
@import "../../common/variables";
@import "../../common/react-transition";

$popover-background-color: $white !default;
$dark-popover-background-color: $dark-gray3 !default;

// $arrow-offset: amount to shift arrow along edge of popover
// $arrow-target-offset: amount to shift arrow relative to target (perpendicular to popover edge)

@mixin popover-sizing($arrow-square-size, $arrow-offset, $arrow-target-offset) {
  // since this is a 45-45-90 triangle, half hypotenuse === side * sqrt(2) / 2 === side / sqrt(2)
  // fun fact: there's no built-in square root function in SASS
  $arrow-diagonal-half-size: math.div($arrow-square-size, 1.41421356);
  // we want the margin to be the size of the part of the arrow that is showing plus
  // a little extra space.
  $content-margin: floor($arrow-diagonal-half-size + $arrow-target-offset);
  // we want to move the arrow out from where it's positioned by the gap amount
  // plus the extra amount of width that is added by its 45 deg rotation.
  $arrow-position: -$arrow-square-size * 0.5 + $arrow-offset;
  // because the 45 deg rotation will make out div stick out a little bit further,
  // we have to slide it over by that amount first and then by the set offset value
  $computed-arrow-offset: ($arrow-diagonal-half-size - $arrow-square-size) * 0.5 + $arrow-offset;

  .#{$ns}-popover-arrow {
    height: $arrow-square-size;
    position: absolute;
    width: $arrow-square-size;

    &::before {
      height: floor($arrow-diagonal-half-size - 1);
      margin: ceil(($arrow-square-size - $arrow-diagonal-half-size) * 0.5);
      // - 1 to compenstate for transparent pixel border shadow
      width: floor($arrow-diagonal-half-size - 1);
    }
  }

  // shift content away from target edge to make space for the arrow
  .#{$ns}-tether-element-attached-bottom.#{$ns}-tether-target-attached-top > & {
    margin-bottom: $content-margin;
    margin-top: -$content-margin;

    > .#{$ns}-popover-arrow {
      bottom: $arrow-position;

      svg {
        transform: rotate(-90deg);
      }
    }
  }

  .#{$ns}-tether-element-attached-left.#{$ns}-tether-target-attached-right > & {
    margin-left: $content-margin;

    > .#{$ns}-popover-arrow {
      left: $arrow-position;

      svg {
        transform: rotate(0);
      }
    }
  }

  .#{$ns}-tether-element-attached-top.#{$ns}-tether-target-attached-bottom > & {
    margin-top: $content-margin;

    > .#{$ns}-popover-arrow {
      top: $arrow-position;

      svg {
        transform: rotate(90deg);
      }
    }
  }

  .#{$ns}-tether-element-attached-right.#{$ns}-tether-target-attached-left > & {
    // div will expand to the right and parent div won't be repositioned,
    // so we need to use negative left margin to move content.
    margin-left: -$content-margin;
    // we keep the positive right margin for ease of arrow positioning.
    margin-right: $content-margin;

    > .#{$ns}-popover-arrow {
      right: $arrow-position;

      svg {
        transform: rotate(180deg);
      }
    }
  }

  // "center" and "middle" attachments
  .#{$ns}-tether-element-attached-middle > & > .#{$ns}-popover-arrow {
    top: 50%;
    transform: translateY(-50%);
  }

  .#{$ns}-tether-element-attached-center > & > .#{$ns}-popover-arrow {
    right: 50%;
    transform: translateX(50%);
  }

  // offset arrow away from corner spots so it appears centered in target
  @each $side in (top, right, left, bottom) {
    // giant selector is 1 character too long :(
    /* stylelint-disable-next-line max-line-length */
    .#{$ns}-tether-element-attached-#{$side}.#{$ns}-tether-target-attached-#{$side} > & > .#{$ns}-popover-arrow {
      #{$side}: $computed-arrow-offset;
    }
  }

  @each $top in (top, middle, bottom) {
    @each $left in (left, center, right) {
      .#{$ns}-tether-element-attached-#{$top}.#{$ns}-tether-element-attached-#{$left} > & {
        @if ($top == middle) {
          // "middle" is tether's way of saying "top == center"
          transform-origin: center $left;
        } @else {
          transform-origin: $top $left;
        }
      }
    }
  }
}

// set background and text colors. also set box-shadow if provided (so modifier styles don't have to
// reassign default shadows).

@mixin popover-appearance(
  $background-color,
  $text-color,
  $shadows,
  $arrow-box-shadow,
  $arrow-border-fill-opacity
) {
  box-shadow: $shadows;

  .#{$ns}-popover-content {
    background: $background-color;
  }

  // Some popovers (like tooltips) invert their foreground/background colors relative
  // to what we expect for the theme. In those cases, we need to override global typography
  // styles to get the right colors.
  .#{$ns}-popover-content,
  .#{$ns}-heading {
    color: $text-color;
  }

  .#{$ns}-popover-arrow::before {
    box-shadow: $arrow-box-shadow;
  }

  .#{$ns}-popover-arrow-border {
    fill: $black;
    fill-opacity: $arrow-border-fill-opacity;
  }

  .#{$ns}-popover-arrow-fill {
    fill: $background-color;

    @media (forced-colors: active) and (prefers-color-scheme: dark) {
      // Windows High Contrast dark theme
      fill: $pt-high-contrast-mode-border-color;
    }
  }
}

@mixin fade-transition() {
  @include react-transition("#{$ns}-popover", (opacity: 0 1), $before: "&");
}

@mixin scale-transition() {
  @include react-transition(
    "#{$ns}-popover",
    (transform: scale(0.3) scale(1)),
    $duration: $pt-transition-duration * 3,
    $easing: $pt-transition-ease-bounce,
    $after: "> &"
  );
}
