////
/// @group accordion
/// Outputs accordion component stylesheet, which can be used with html details element or custom disclosure components.
////

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

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


// Used for function fallback
$-fallbacks: (
  "border-radius" : (
    "function" : meta.get-function("get", false, "element"),
    "property" : "border-radius"
  ),
);

/// Module Settings
/// @type Map
/// @prop {Color}  background-color  [background] This is the background color of the accordion before it is expanded.
/// @prop {Color}  background-color-open  [white] This is the background color of the accordion when it is expanded. This will change the background color of the accordion's summary as well as the details.
/// @prop {String} border-color ["rule-light"] The color of the accordion border.
/// @prop {Boolean|Number} border-radius  [true] This applies a rounding of edges for the accordion. If there are multiple accordions in a stack, this will only apply to the top of the first accordion and the bottom of the last accordion.
/// @prop {Dimension} border-width  [1px] The width of the borders of the accordions.
/// @prop {CssValue} box-shadow  [none] Adds a box shadow to accordion container.
/// @prop {Dimension} margin  [(1.5em 0)] This is the margin above and below the accordion. Multiple Accordions will stack. See margin-between below.
/// @prop {Dimension} margin-between  [0] This adds a margin between adjacent accordions. By default, accordions do not have any net margin between each other.
/// @prop {Dimension} padding-x  [1.5em] Singular value for the left and right padding.
/// @prop {Dimension} padding-y  [1.5em] Singular value for the top and bottom padding.
/// @prop {Color} icon-background-color  [transparent] The background color of the icon.
/// @prop {Color} icon-background-color-hover  [transparent] The background color of the icon when hovered or focused.
/// @prop {Number} icon-border-radius  [50%] The border-radius of the icon.
/// @prop {String} icon-color  [link] Color of the icon. This uses color.scss, so the value of this option should be a color variable from color.scss.
/// @prop {String} icon-color-hover  [link-hover] Color of the icon when hovered or focused on. This uses color.scss, so the value of this options should be a color variable from color.scss.
/// @prop {Dimension} icon-font-size  [1em] The font-size of the icon.
/// @prop {Dimension} icon-margin [1em] The margin to the left of the icon.
/// @prop {Dimension} icon-size  [auto] The size of the icon. Used as the base in the flex property.
/// @prop {Dimension} icon-stroke-width [0.15em] The stroke width of the icon.
/// @prop {Color} summary-background-color  [#f6f6f6] The background color for the summary (toggle button) of the accordion.
/// @prop {Color} summary-background-color-hover [null] The background color for the summary (toggle button) of the accordion when hovered.
/// @prop {Color} summary-color  [null] The color of the text in the accordion summary.
/// @prop {Color} summary-color-hover  [null] The color of the text in the accordion summary when hovering or focusing on it.
/// @prop {Dimension} summary-line-height  [null] Adjusts the line height of the summary element.
/// @prop {Dimension} summary-padding-y  [1em] The vertical padding of the summary.
/// @prop {String|Boolean} summary-type-size  ["large"] The typography size of the text in the accordion summary. Can be a boolean to disable.
/// @prop {Boolean} summary-border-enabled [true] Whether the summary has a border when the accordion is open.
/// @prop {Color} summary-border-color [rule-light] The color of the summary border.
/// @prop {Dimension} summary-border-width [1px] The width of the summary border.
/// @prop {Dimension} transparent-content-padding [(0.25em 0)] The padding of the content area for transparent accordions.
/// @prop {Dimension} borderless-margin-between  [0.5em] Margin between accordions when using no-border modifier.
/// @prop {String} active-selector ['.is-active'] The selector used for the active state of a non-<details> accordion.

$config: (
  "background-color":               "background",
  "background-color-open":          white,
  "border-color":                   "rule-light",
  "border-radius":                  true,
  "border-width":                   1px,
  "box-shadow":                     none,
  "margin":                         (1.5em 0),
  "margin-between":                 0,
  "padding-x":                      1.25em,
  "padding-y":                      1.25em,
  "icon-background-color":          transparent,
  "icon-background-color-hover":    transparent,
  "icon-border-radius":             50%,
  "icon-color":                     "link",
  "icon-color-hover":               "link-hover",
  "icon-font-size":                 1em,
  "icon-margin":                    1em,
  "icon-size":                      auto,
  "icon-stroke-width":              0.15em,
  "summary-background-color":       #f6f6f6,
  "summary-color":                  null,
  "summary-background-color-hover": null,
  "summary-color-hover":            null,
  "summary-line-height":            null,
  "summary-padding-y":              1em,
  "summary-type-size":              false,
  "summary-font-weight":            bold,
  "summary-border-enabled":         true,
  "summary-border-color":           "rule-light",
  "summary-border-width":           1px,
  "transparent-content-padding":    (1em 0),
  "borderless-margin-between":      0.5em,
  "active-selector":                ".is-active"
) !default;

/// Change modules $config
/// @param {Map} $changes Map of changes
/// @example scss
///   @include ulu.component-accordion-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-accordion-get("property");

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

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

@mixin styles {
  $prefix: selector.class("accordion");
  $active-selector: get("active-selector");
  $padding-x: get("padding-x");
  $border: get("border-width") solid color.get(get("border-color"));

  // When not one of our custom classed details components
  #{ $prefix } {
    --ulu-accordion-radius-top: #{get("border-radius")};
    --ulu-accordion-radius-bottom: #{get("border-radius")};
    position: relative; // For pushing to the top when in accordion groups
    padding: 0;
    margin: get("margin");
    border: $border;
    background-color: color.get(get("background-color"));
    box-shadow: get("box-shadow");
    border-radius: var(--ulu-accordion-radius-top) var(--ulu-accordion-radius-top) var(--ulu-accordion-radius-bottom) var(--ulu-accordion-radius-bottom);

    // Sibling before sets the gap
    & + #{ $prefix } {
      margin-top: 0;
    }

    // If no space get rid of border radiuses
    @if (get("margin-between") == 0) {
      &:has(+ #{ $prefix }) {
        --ulu-accordion-radius-bottom: 0;
        margin-bottom: 0;
      }
      & + #{ $prefix } {
        --ulu-accordion-radius-top: 0;
        margin-top: -(get("border-width")); // Pull border over top
      }
    } @else {
      &:has(+ #{ $prefix }) {
        margin-bottom: get("margin-between");
      }
    }
    
    &[open], 
    &#{ $active-selector }  {
      background-color: color.get(get("background-color-open"));
      z-index: 2; // Above other details/accordions
      > #{ $prefix }__summary {
        border-bottom-left-radius: 0;
        border-bottom-right-radius: 0; 

        @if (get("summary-border-enabled")) { 
          &::after {
            content: "";
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            height: get("summary-border-width");
            background-color: color.get(get("summary-border-color"));
          }
        }
      }
    }
  }
  #{ $prefix }__summary {
    position: relative; // For pseudo border (done this way for animations)
    display: flex;
    width: 100%; // For <button>
    background-color: color.get(get("summary-background-color"));
    color: color.get(get("summary-color"));
    line-height: get("summary-line-height");
    padding: get("summary-padding-y") $padding-x;
    border-radius: var(--ulu-accordion-radius-top) var(--ulu-accordion-radius-top) var(--ulu-accordion-radius-bottom) var(--ulu-accordion-radius-bottom);
    font-weight: get("summary-font-weight");
    cursor: pointer;
    align-items: center;

    @include typography.optional-size(get("summary-type-size"), $only-font-size: true);
    @include element.summary-remove-marker();
    &:hover,
    &:focus {
      background-color: color.get(get("summary-background-color-hover"));
      color: color.get(get("summary-color-hover"));
      #{ $prefix }__icon {
        background-color: color.get(get("icon-background-color-hover"));
        color: color.get(get("icon-color-hover"));
      }
    }
  }
  #{ $prefix }__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 get("icon-size");
    color: color.get(get("icon-color"));
    margin-left: auto;
    padding-left: get("icon-margin");
    background-color: color.get(get("icon-background-color"));
    border-radius: get("icon-border-radius");
    width: get("icon-size");
    height: get("icon-size");
    font-size: get("icon-font-size");
    line-height: 1;
  }
  #{ $prefix }__content {
    padding: get("padding-y") $padding-x;
    border-bottom-left-radius: var(--ulu-accordion-radius-bottom);
    border-bottom-right-radius: var(--ulu-accordion-radius-bottom);
  }
  #{ $prefix }--transparent {
    border-left: none;
    border-right: none;
    background-color: transparent !important;
    border-radius: 0;

    // Transparent always collapses space
    @if (get("margin-between") != 0) {
      &:has(+ #{ $prefix }) {
        margin-bottom: 0;
      }
      & + #{ $prefix } {
        margin-top: -(get("border-width")); // Pull border over top
      }
    }
    > #{ $prefix }__summary,
    > #{ $prefix }__content {
      padding-left: 0;
      padding-right: 0;
      background-color: transparent;
      border: none !important;
      border-radius: 0 !important;
    }
    > #{ $prefix }__content {
      padding: get("transparent-content-padding");
    }
  }
  #{ $prefix }--borderless {
    border: none;
    &:has(+ #{ $prefix }) {
      margin-bottom: 0;
    }
    & + #{ $prefix }--borderless {
      margin-top: calc(get("borderless-margin-between") - get("border-width"));
    }
    > #{ $prefix }__summary,
    > #{ $prefix }__content {
      border-radius: get("border-radius");
    }
    &[open],
    &#{ $active-selector } {
      & > #{ $prefix }__summary {
        border-radius: get("border-radius");
        border-bottom: none;
        @if (get("summary-border-enabled")) { 
          &::after {
            content: none;
          }
        }
      }
    }
  }
}
