////
/// @group css-icon
/// Simple icons that only require CSS selectors, used for defaults (JS, etc). Not meant to be replacement for complete icon library. Note the selectors currently can't be modified.
////

// Notes: 
// - Using this to avoid having coupled image in base, can easily switch 
//   to font awesome in production
// - Can't use clip-path with svg clipPath without it being loaded in document (more coupling/setup)
// - Can't use mask-image until it's more universal (could create icons the 
//   old way and export and use the masks in the future (complex shapes)

// Note: File size is 7kb (1kb gzip) (2024-09-25)(
// Benchmarks:
// - 2024/09/25 - 1.3kb - File size (7kb unzipped)
// - 2024/10/14 - 1.3kb - Tested after adding active icons and using attribute selectors

@use "sass:map";
@use "sass:math";
@use "../color";

@use "../utils";

/// Module Settings
/// @type Map
/// @prop {String} active-selector [details[open] > summary &, &.is-active] The active selector for css-icon.
/// @prop {Color} color [currentColor] The color of the css-icon.
/// @prop {CssValue} font-family [('Courier New', monospace)]
/// @prop {CssValue} margin [(0 0.15em)] The icon's margin
/// @prop {Dimension} size [1.1em] The width, height and font size of the css-icon.
/// @prop {Dimension} stroke-border-radius [1px] The rounding of the strokes for css-icon.
/// @prop {Dimension} stroke-width [0.15em] The stroke width of the css-icon.
/// @prop {Dimension} drag-gap-multiplier [0.75] Multiplier used to adjust the space between drag-x/drag-y icons (used for all stroke sizes)
/// @prop {Dimension} text-offset [0.05em] When using an icon with text, adds a margin to match the text height.
/// @prop {Dimension} text-size [1em] font-size of the icon when using text.
/// @prop {Dimension} vertical-align [-0.2em] Vertical-align for css-icon 
/// @prop {Time} transition-duration [200ms] The duration length for the transition.
/// @prop {CssValue} transition-timing-function [ease-in] The timing function for the transition.
/// @prop {Map} stroke-sizes [Map] Modifiers to adjust stroke sizes for the icons.

$config: (
  "active-selector" : "details[open] > summary &, &.is-active",
  "color" : currentColor,
  "font-family" : ('Courier New', monospace),
  "margin" : (0 0.15em),
  "size" : 1.15em,
  "stroke-border-radius" : null,
  "stroke-width" : 3px,
  "drag-gap-multiplier" : 0.75,
  "text-offset" : 0.05em,
  "text-size" : 1em,
  "vertical-align" : -0.25em,
  "transition-duration" : 200ms, 
  "transition-timing-function" : ease-in,
  "stroke-sizes" : (
    "large" : (
      "stroke-width" : 5px,
      "stroke-border-radius" : 2px
    )
  )
);

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

@function get($name) {
  @return utils.require-map-get($config, $name, "css-icon [config]");
}

/// Used to style active icons
/// - Probably only useful for extending this component and matching active selector
/// - Used internally in module

@mixin when-active() {
  #{ get("active-selector") } {
    @content;
  }
}

@mixin for-each-stroke() {
  @each $name, $props in get("stroke-sizes") {
    $stroke-width: map.get($props, "stroke-width");
    $stroke-border-radius: map.get($props, "stroke-width");
    .css-icon--stroke-#{ $name } {
      @content($stroke-width, $stroke-border-radius);
    }
  }
}

/// Output CSS icon component stylesheet
/// @example scss
///  @include ulu.component-css-icon-styles();

@mixin styles {
  $border: get("stroke-width") solid color.get(get("color"));
  $size: get("size");
  $stroke-width: get("stroke-width");
  $half-height: math.div(get("size"), 2);
  $half-stroke-width: math.round(math.div(get("stroke-width"), 2));


  .css-icon {
    display: inline-block;
    position: relative;
    width: get("size");
    height: get("size");
    transform-origin: center;
    vertical-align: get("vertical-align");
    font-variant: normal;
    text-rendering: auto;
    line-height: 1;
    margin: get("margin");
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    // Icons that share pseudos for strokes
    &::before,
    &::after {
      // content: "";
      display: block;
      position: absolute;
      width: 100%;
      height: $stroke-width;
      top: 50%;
      left: 50%;
      background-color: color.get(get("color")); 
      transform: translateX(-50%);
      margin-top: -($half-stroke-width);
      border-radius: get("stroke-border-radius");
    }
  }
  @include for-each-stroke() using ($alt-width, $alt-border-radius) {
    &::before,
    &::after {
      height: $alt-width;
      margin-top: -(math.div($alt-width, 2));
      border-radius: $alt-border-radius;
    }
  }
  .css-icon--plus,
  .css-icon--plus-to-minus,
  .css-icon--minus,
  .css-icon--close {
    &::before,
    &::after {
      content: "";
    }
  }


  // Solid icons
  [class*="css-icon--circle"],
  [class*="css-icon--square"] {
    background-color: color.get(get("color"));
  }
  [class*="css-icon--circle"] {
    border-radius: 50%;
  }

  .css-icon--square {
    transform: scale(0.9);
  }
  .css-icon--square,
  .css-icon--circle,
  .css-icon--circle-outline,
  .css-icon--square-outline {
    &::before,
    &::after {
      content: none;
    }
  }
  .css-icon--circle-outline,
  .css-icon--square-outline {
    background-color: transparent;
    border: $border;
  }

  
  .css-icon--circle-info,
  .css-icon--circle-question {
    &::before {
      content: "i";
      text-align: center;
      font-size: get("text-size");
      font-family: get("font-family");
      font-weight: bold;
      margin-top: get("text-offset");
      color: color.get(get("color"));
      height: auto;
      left: 0;
      right: 0;
      background-color: transparent;
      filter: invert(1) brightness(1.5);
      transform: translateY(-50%);
    }
    &::after {
      content: none;
    }
  }
  .css-icon--circle-question { 
    &::before {
      content: "?";
    }
  }

  [class*="css-icon--arrow"] {
    &::before,
    &::after {
      content: "";
      transform: translateY(-50%);
      margin-top: 0;
    }
  }
  
  // Arrow uses same equilateral triangle
  [class*="css-icon--triangle"],
  [class*="css-icon--arrow"]::after {
    background-color: color.get(get("color"));
    clip-path: polygon(10% 10%, 90% 50%, 10% 90%);
  }
  [class*="css-icon--arrow"] {
    &::before {
      content: "";
      width: 70%;
      left: 0;
    }
    // Note triangle clip-path is defined above with the solid triangle
    &::after {
      content: "";
      border-radius: 0;
      height: 100%;
      width: 55%;
      right: 0;
      left: auto;
    }
  }
  [class*="css-icon--angle"] {
    transform: rotate(135deg);
    &::before,
    &::after {
      content: "";
      top: 30%;
      left: 30%;
      width: 70%;    
      transform: none;
      margin-top: 0;
    }
    &::after {
      width: $stroke-width;
      height: 70%;
    }
  }
  @include for-each-stroke() using ($alt-width, $alt-border-radius) {
    &[class*="css-icon--angle"] {
      &::after {
        width: $alt-width;
      }
    }
  }
  .css-icon--angle-left,
  .css-icon--arrow-left {
    transform: rotate(315deg);
  }
  .css-icon--angle-up,
  .css-icon--angle-up-to-down {
    transform: rotate(45deg);
  }
  .css-icon--angle-down,
  .css-icon--angle-down-to-up {
    transform: rotate(225deg);
  }

  // Centered pseudos offset by half of stroke before transform
  // Icons with centered pseudos

  .css-icon--plus,
  .css-icon--plus-to-minus {
    &::before {
      transform: translateX(-50%) rotate(90deg);
    }
    &::after {
      transform: translateX(-50%);
    }
  }
  .css-icon--minus {
    &::before {
      content: none;
    }
    &::after {
      transform: translateX(-50%);
    }
  }
  .css-icon--close {
    &::before {
      transform: translate(-50%) rotate(45deg);
    }
    &::after {
      transform: translate(-50%) rotate(-45deg);
    }
  }
  [class*="css-icon--drag"] {
    &::before {
      content: "";
      // Make up for margin-top by default
      margin-top: -(($stroke-width + $stroke-width) * get("drag-gap-multiplier"));
    }
    &::after {
      content: "";
      margin-top: $stroke-width * get("drag-gap-multiplier");
    }
  }

  @include for-each-stroke() using ($alt-width, $alt-border-radius) {
    // $drag-gap-multiplier: map.get($props, "drag-gap-multiplier");
    // $drag-gap-multiplier: if($drag-gap-multiplier, $drag-gap-multiplier, 0);
    &[class*="css-icon--drag"] {
      &::before {
        margin-top: -(($alt-width + $alt-width) * get("drag-gap-multiplier"));
      }
      &::after {
        margin-top: $alt-width * get("drag-gap-multiplier");
      }
    }
  }
  // For the menu icon the blocks are stacked with box shadow being the 
  // third bar
  .css-icon--menu,
  .css-icon--menu-to-close {
    display: inline-flex;
    align-items: center;
    flex-direction: column;
    justify-content: center;
    vertical-align: middle;
    &::before,
    &::after {
      content: "";
      position: static;
      transform: none;
      margin-top: 0;
    }
    &::before {
      box-shadow: 0px ($stroke-width * 2 + 1px) color.get(get("color"));
      margin-bottom: ($stroke-width * 3) + 2px;
    }
  }
  @include for-each-stroke() using ($alt-width, $alt-border-radius) {
    &.css-icon--menu,
    &.css-icon--menu-to-close {
      &::before {
        box-shadow: 0px ($alt-width * 2 + 1px) color.get(get("color"));
        margin-bottom: ($alt-width * 3) + 2px;
      }
    }
  }

  // Rotations
  .css-icon--triangle-left,
  .css-icon--arrow-left {
    transform: rotate(180deg);
  }
  .css-icon--drag-x,
  .css-icon--triangle-up,
  .css-icon--arrow-up {
    transform: rotate(270deg);
  }
  .css-icon--triangle-down,
  .css-icon--arrow-down {
    transform: rotate(90deg);
  }
  .css-icon--drag-both {
    transform: rotate(-45deg);
    &::before {
      transform: translateX(-50%) scale(0.8);
      margin-top: -($stroke-width);
    }
    &::after {
      transform: translateX(-50%) scaleX(0.5) scaleY(0.8);
    }
  }

  // Active icons
  .css-icon--plus-to-minus {
    &,
    &::before,
    &::after {
      transition: get("transition-duration") get("transition-timing-function");
      transition-property: opacity, transform;
    }
    @include when-active() {
      &::before {
        opacity: 0;
        transform: translateX(-50%) rotate(180deg);
      }
    }
  }
  
  .css-icon--angle-right-to-down,
  .css-icon--angle-up-to-down,
  .css-icon--angle-down-to-up {
    @include when-active() {
      transition-duration: get("transition-duration");
      transition-property: transform;
    }
  }
  .css-icon--angle-right-to-down,
  .css-icon--angle-up-to-down {
    @include when-active() {
      transform: rotate(225deg);
    }
  }
  .css-icon--angle-down-to-up {
    @include when-active() {
      transform: rotate(45deg);
    }
  }
  .css-icon--angle-up-to-down,
  .css-icon--angle-down-to-up {
    @include when-active() {
      transition-duration: get("transition-duration") * 2;
    }
  }
  .css-icon--menu-to-close {
    @include when-active() {
      animation: UluScaleIn get("transition-duration") get("transition-timing-function") forwards;
      &::before,
      &::after {
        position: absolute;
        top: 50%;
        transition: none;
        transform: translate(-50%) rotate(-45deg);
      }
      &::before {
        box-shadow: none;
        transform: translate(-50%) rotate(45deg);
      }
    }
  }
}