////
/// @group popover
////

// NOTE: This is an updated version that uses floating UI

@use "sass:math";
@use "sass:map";
@use "sass:meta";

@use "../selector";
@use "../typography";
@use "../utils";
@use "../color";
@use "../layout";
@use "../element";

// Used for function fallback
$-fallbacks: (
  "box-shadow" : (
    "function" : meta.get-function("get", false, "element"),
    "property" : "box-shadow-above",
  ),
  "z-index" : (
    "function" : meta.get-function("get", false, "layout"),
    "property" : "z-index-fixed",
  ),
);

/// Module Settings
/// @type Map
/// @prop {Dimension} arrow-size [16px] Size of the dropdown arrow.
/// @prop {Boolean} arrow-box-shadow [true] When true the arrow will get the popover's box shadow. Note if the box shadow is not a list (for example custom property), the mask won't be calculated from the box-shadow (use arrow-box-shadow-extent to specify manually)
/// @prop {Number} arrow-box-shadow-extent [null] If set will determine the amount of overlap added to the arrow mask, else it's calculated automatically by the box-shadow option (can be used if box-shadow is custom property)
/// @prop {Color} background-color [white] Background color of the popover.
/// @prop {Dimension} border-radius [6px] Border radius of the popover.
/// @prop {Color} color [inherit] Text color of the popover.
/// @prop {Dimension} max-width [90vw] Max width of the popover.
/// @prop {Dimension} max-height [25rem] Max height of the popover.
/// @prop {Dimension} padding [1rem] Padding of the popover.
/// @prop {Dimension} padding-large [2rem] Padding of the popover if using "--large" or "--large-x" styling.
/// @prop {Dimension} type-size [null] Font size of the popover.
/// @prop {Number} z-index [true] z-index of the popover.
/// @prop {CssValue} box-shadow [true] Box shadow of the popover.
/// @prop {Color} header-background-color [#ccc] Background color of the popover header
/// @prop {Color} header-color [null] Text color for the header.
/// @prop {Color} header-media-background-color [black] background color for header media.
/// @prop {Dimension} header-padding-y [0.25rem] Vertical padding of the header.
/// @prop {Color} footer-background-color [#ccc] Background color of the footer.
/// @prop {Color} footer-border-top [1px solid #dfdfdf] Optional border used to separate the content from footer
/// @prop {Color} footer-color [null] Text color of the footer.
/// @prop {Dimension} footer-padding-y [0.25rem] Vertical padding of the footer.
/// @prop {Dimension} footer-padding-y-large [0.5rem] Vertical padding of the footer if using "--large" or "--large-x" styling.
/// @prop {Color} tooltip-background-color [white] Background color of the tooltip.
/// @prop {Color} tooltip-color [null] Font color of the tooltip.
/// @prop {Dimension} tooltip-max-width [20rem] Max width of the tooltip.
/// @prop {Dimension} tooltip-padding [0.5rem] Padding of the tooltip.
/// @prop {Dimension} tooltip-width [auto] Width of the tooltip.
/// @prop {Dimension} width [15rem] Width of the popover.
/// @prop {Dimension} width-large [30rem] Width of the popover if using "--large".
/// @prop {Dimension} width-large-x [50rem] Width of the popover if using "--large-x".

$config: (
  "arrow-size"                   : 16px,
  "arrow-box-shadow"             : true,
  "arrow-box-shadow-extent"      : null,
  "background-color"             : white,
  "border-radius"                : 6px,
  "color"                        : inherit,
  "max-width"                    : 90vw,
  "max-height"                   : 25rem,
  "padding"                      : 1rem,
  "padding-large"                : 2rem,
  "type-size"                    : null,
  "z-index"                      : true,
  "box-shadow"                   : true,
  "header-background-color"      : #ccc,
  "header-color"                 : null,
  "header-media-background-color": black,
  "header-padding-y"             : 0.25rem,
  "footer-border-top"            : 1px solid #dfdfdf,  
  "footer-background-color"      : #ccc,
  "footer-color"                 : null,
  "footer-padding-y"             : 0.25rem,
  "footer-padding-y-large"       : 0.5rem,
  "tooltip-background-color"     : white,
  "tooltip-color"                : null,
  "tooltip-max-width"            : 20rem,
  "tooltip-padding"              : 0.5rem,
  "tooltip-width"                : auto,
  "width"                        : 15rem,
  "width-large"                  : 30rem,
  "width-large-x"                : 50rem,
  ) !default;
  
/// Change modules $config
/// @param {Map} $changes Map of changes
/// @example scss
///   @include ulu.component-popover-set(( "property" : value ));

@mixin set($changes) {
  $config: map.merge($config, $changes) !global;
}

/// Get a config option
/// @param {Map} $name Name of property
/// @example scss
///   @include ulu.component-popover-get("property");

@function get($name) {
  $value: utils.require-map-get($config, $name, "component-popover [config]");
  @return utils.function-fallback($name, $value, $-fallbacks);
}

/// Prints component styles
/// @example scss
///  @include ulu.component-popover-styles();

@mixin styles {
  $prefix: selector.class("popover");

  @if (get("arrow-size")) {
    @include -arrow-styles();
  }
  // Default position is on the right of the container (Popper handles positioning)
  #{ $prefix } {
    display: none;
    position: absolute;
    z-index: get("z-index") + 1;
    background-color: color.get(get("background-color"));
    color: color.get(get("color"));
    width: get("width");
    max-width: get("max-width");
    box-shadow: get("box-shadow");
    border-radius: get("border-radius");
    text-align: left;
    @if (get("type-size")) {
      @include typography.size(get("type-size"));
    }
    &.is-active {
      display: block;
    }
  }
  #{ $prefix }__inner,
  #{ $prefix }__header,
  #{ $prefix }__footer {
    display: block;
    border-radius: get("border-radius");
    position: relative;
    z-index: 2; // Above arrow
    flex: 0;
  }
  #{ $prefix }__inner {
    overflow-y: auto;
    max-height: get("max-height");
    padding: get("padding");
    flex: 1; // When used with footer
  }
  // Image, video above content
  #{ $prefix }__header {
    overflow: hidden;
    padding: get("header-padding-y") get("padding");
    color: color.get(get("header-color"));
    background-color: color.get(get("header-background-color"));
  }
  #{ $prefix }__header--media {
    padding: 0;
    background-color: color.get(get("header-media-background-color"));
  }
  #{ $prefix }__footer {
    border-top: get("footer-border-top");
    padding: get("footer-padding-y") get("padding");
    color: color.get(get("footer-color"));
    background-color: color.get(get("footer-background-color"));
    border-top-left-radius: 0;
    border-top-right-radius: 0;
  }
  #{ $prefix }__header:has(+ #{ $prefix }__inner),
  #{ $prefix }__header:has(+ #{ $prefix }__footer),
  #{ $prefix }__inner:has(+ #{ $prefix }__footer) {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }

  // Modifiers
  #{ $prefix }--tooltip {
    width: get("tooltip-width");
    max-width: min(get("max-width"), get("tooltip-max-width"));
    color: color.get(get("tooltip-color"));
    background-color: color.get(get("tooltip-background-color"));
    pointer-events: none;
    #{ $prefix }__inner {
      padding: get("tooltip-padding");
      min-height: 0;
    }
  }
  // For fixed strategy
  #{ $prefix }--fixed {
    position: fixed;
  }
  // If you want to do something custom (and have it touch the edges)
  #{ $prefix }--no-padding {
    #{ $prefix }__inner {
      padding: 0;
    }
  }
  #{ $prefix }--large {
    width: get("width-large");
  }
  #{ $prefix }--large-x {
    width: get("width-large-x");
  }
  #{ $prefix }--large,
  #{ $prefix }--large-x {
    #{ $prefix }__inner {
      padding: get("padding-large");
    }
    #{ $prefix }__footer {
      padding: get("footer-padding-y-large") get("padding-large");
    }
  }
  #{ $prefix }--prints {
    @media print {
      display: block;
      position: static;
      width: auto;
      box-shadow: none;
      max-width: none;
      #{ $prefix }__arrow  {
        display: none;
      }
    }
  }
}

@mixin -arrow-styles() {
  @if get("arrow-box-shadow") {
    @include -arrow-styles-with-box-shadow();
  } @else {
    @include -arrow-styles-simple();
  }
}

// Internal mixin for original arrow styles without box-shadow
@mixin -arrow-styles-simple() {
  $prefix: selector.class("popover");
  $size: get("arrow-size");
  $half: math.div($size, 2);

  #{ $prefix }__arrow {
    visibility: hidden;
    z-index: 1;
    &,
    &::before {
      display: block;
      position: absolute;
      width: $size;
      height: $size;
      background: inherit;
    }
    &::before {
      visibility: visible;
      content: '';
      transform: rotate(45deg);
    }
    [data-placement^="top"] > & {
      bottom: -($half);
    }
    [data-placement^="bottom"] > & {
      top: -($half);
    }
    [data-placement^="left"] > & {
      right: -($half);
    }
    [data-placement^="right"] > & {
      left: -($half);
    }
  }
  // Account for footer and change arrow color when positioned next to it
  #{ $prefix }__footer ~ #{ $prefix }__arrow {
    [data-placement^="top"] > & {
      &::before {
        background-color: get("footer-background-color");
      }
    }
  }
}

// Internal mixin for arrow styles when using the mask (extra pseudo element)
@mixin -arrow-styles-with-box-shadow() {
  $prefix: selector.class("popover");
  $box-shadow: get("box-shadow");
  $size: get("arrow-size");
  $half: math.div($size, 2);
  $size-info: utils.number-info($size);
  $unitless: map.get($size-info, "value");
  $unit: map.get($size-info, "unit");
  $hypotenuse: utils.hypotenuse($unitless, $unitless);
  $hypotenuse-half: math.div($hypotenuse, 2);
  $manual-extent: get("arrow-box-shadow-extent");
  $shadow-extent: if(
    $manual-extent,
    $manual-extent,
    if(utils.is-list($box-shadow), utils.box-shadow-extent($box-shadow), 5px)
  );
  $overlap: utils.strip-unit($shadow-extent);
  $mask-height: utils.add-unit($hypotenuse-half + $overlap, $unit);
  $mask-width: utils.add-unit($hypotenuse + $overlap, $unit);
  
  #{ $prefix }__arrow {
    visibility: hidden;
    z-index: 1;
    &,
    &::before,
    &::after {
      display: block;
      position: absolute;
      width: $size;
      height: $size;
      background: inherit;
    }
    &::before,
    &::after {
      visibility: visible;
      content: '';
    }
    &::before {
      box-shadow: get("box-shadow");
      transform: rotate(45deg);
    }
    // Masking shape
    &::after {
      top: 50%;
      left: 50%;
      transform: translateX(-50%);
      height: $mask-height;
      width: $mask-width;
    }
    [data-placement^="top"] > & {
      bottom: -($half);
      transform: rotate(180deg); // Rotate w. mask
    }
    [data-placement^="bottom"] > & {
      top: -($half);
    }
    [data-placement^="left"] > & {
      right: -($half);
      transform: rotate(90deg); // Rotate w. mask
    }
    [data-placement^="right"] > & {
      left: -($half);
      transform: rotate(-90deg); // Rotate w. mask
    }
  }
  // Account for footer and change arrow color when positioned next to it
  #{ $prefix }__footer ~ #{ $prefix }__arrow {
    [data-placement^="top"] > & {
      &::before,
      &::after {
        background-color: get("footer-background-color");
      }
    }
  }
}