////
/// @group spoke-spinner
/// A spoke style spinner/loader icon, requires ulu.base-keyframes
////

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

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

/// Module Settings
/// @type Map

$config: (
  "size" : 48px,
  "spoke-width" : 3px,
  "spoke-height" : 12px,
  "color" : "accent",
  "border-radius" : 2px,
  "duration" :  1.2s
) !default;

/// Map of other sizes (use as modifiers), same properties as config/defaults
$styles: () !default;

/// Change modules $config
/// @param {Map} $changes Map of changes
/// @example scss
///   @include ulu.component-spoke-spinner-set(( "property" : value ));

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

/// Set tag styles 
/// @param {Map} $changes Map of changes
/// @param {String} $merge-mode Merge mode see utils.map-merge() [null|"deep"|"overwrite"]

@mixin set-styles($changes, $merge-mode: null) {
  $styles: utils.map-merge($styles, $changes, $merge-mode) !global;
}

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

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

/// Output component stylesheet
/// @example scss
///  @include ulu.component-spoke-spinner-styles();
/// @example html Example markup
/// <div class="spoke-spinner">
///   <div class="spoke-spinner__spinner">
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///     <div></div>
///   </div>
/// </div>

@mixin styles {
  $prefix: selector.class("spoke-spinner");


  $size: get("size");
  $sizeHalf: math.div($size, 2);

  $spoke-width: get("spoke-width");
  $spoke-widthHalf: math.div($spoke-width, 2);

  #{ $prefix } {
    position: relative;
    vertical-align: middle; // When used as inline-block
  }
  #{ $prefix }__spinner {
    display: inline-block;
    position: relative;
    width: $size;
    height: $size;
  }
  #{ $prefix }__spinner div {
    transform-origin: $sizeHalf $sizeHalf;
    animation: UluFadeOut get("duration") linear infinite;
  }
  #{ $prefix }__spinner div::after {
    content: " ";
    display: block;
    position: absolute;
    top: 0;
    left: $sizeHalf - $spoke-widthHalf;
    width: $spoke-width;
    height: get("spoke-height");
    border-radius: get("border-radius");
    background: color.get(get("color"));
  }
  #{ $prefix }__spinner div:nth-child(1) {
    transform: rotate(0deg);
    animation-delay: -1.1s;
  }
  #{ $prefix }__spinner div:nth-child(2) {
    transform: rotate(30deg);
    animation-delay: -1s;
  }
  #{ $prefix }__spinner div:nth-child(3) {
    transform: rotate(60deg);
    animation-delay: -0.9s;
  }
  #{ $prefix }__spinner div:nth-child(4) {
    transform: rotate(90deg);
    animation-delay: -0.8s;
  }
  #{ $prefix }__spinner div:nth-child(5) {
    transform: rotate(120deg);
    animation-delay: -0.7s;
  }
  #{ $prefix }__spinner div:nth-child(6) {
    transform: rotate(150deg);
    animation-delay: -0.6s;
  }
  #{ $prefix }__spinner div:nth-child(7) {
    transform: rotate(180deg);
    animation-delay: -0.5s;
  }
  #{ $prefix }__spinner div:nth-child(8) {
    transform: rotate(210deg);
    animation-delay: -0.4s;
  }
  #{ $prefix }__spinner div:nth-child(9) {
    transform: rotate(240deg);
    animation-delay: -0.3s;
  }
  #{ $prefix }__spinner div:nth-child(10) {
    transform: rotate(270deg);
    animation-delay: -0.2s;
  }
  #{ $prefix }__spinner div:nth-child(11) {
    transform: rotate(300deg);
    animation-delay: -0.1s;
  }
  #{ $prefix }__spinner div:nth-child(12) {
    transform: rotate(330deg);
    animation-delay: 0s;
  }

  // Map of config props needed for a new style, omitting props like color that aren't required
  $required: (
    "size" : get("size"),
    "spoke-width" : get("spoke-width"),
    "spoke-height" : get("spoke-height"),
  );

  @each $name, $style in $styles {
    $merged: map.merge($required, $style);

    $size: map.get($merged, "size");
    $sizeHalf: math.div($size, 2);

    $spoke-width: map.get($merged, "spoke-width");
    $spoke-widthHalf: math.div($spoke-width, 2);

    #{ $prefix }--#{ $name } {
      #{ $prefix }__spinner {
        width: $size;
        height: $size;
      }
      #{ $prefix }__spinner div {
        transform-origin: $sizeHalf $sizeHalf;
        animation-duration: map.get($merged, "duration");
      }
      #{ $prefix }__spinner div::after {
        left: $sizeHalf - $spoke-widthHalf;
        width: $spoke-width;
        height: map.get($merged, "spoke-height");
        border-radius: map.get($merged, "border-radius");
        background: color.get(map.get($merged, "color"));
      }
    }
  }
}