@use 'sass:map';
@use 'sass:math';
@use 'sass:meta';
@use 'sass:list';
@use 'sass:color';
@use 'sass:string';

// Define CSS variables recursively from a map
@mixin vars($map, $prefix: null) {
  @each $name, $value in $map {
    @if meta.type-of($value) == map {
      $new-prefix: $prefix;
      @if string.slice($name, 1, 1) != '-' {
        $new-prefix: if(sass($prefix): #{$prefix}-#{$name}; else: #{$name});
      }
      @include vars($value, $new-prefix);
    } @else {
      $var-name: if(sass($prefix): --#{$prefix}-#{$name}; else: --#{$name});
      #{$var-name}: #{$value};
    }
  }
}

// Define tints/shades for colors in a palette
// $palette map must contain 'colors' and 'tints' keys
@function color-palette($palette, $bg, $fg) {
  $output: ();
  @each $name, $color in map.get($palette, colors) {
    @each $level, $amount in map.get($palette, tints) {
      $var-name: #{$name}-#{$level};
      $mix-with: if(sass($amount > 0): $bg; else: $fg);
      $mixed-color: color.mix($mix-with, $color, math.abs($amount), $method: rgb);
      $output: map.set($output, $var-name, to-hex($mixed-color));
    }
  }
  @return $output;
}

// Generate colors map for building a theme
// $colors map must contain 'bg' and 'fg' keys
// $palette map must contain 'colors' and 'tints' keys
@function colors-map($colors, $palette) {
  $bg: map.get($colors, 'bg');
  $fg: map.get($colors, 'fg');
  @return map.merge($colors, color-palette($palette, $bg, $fg));
}

// Returns a list of keys converted into strings,
// mainly used to get a palette color names as strings
// to avoid sass interpolation warnings
@function string-keys($map) {
  $output: ();
  @each $key in map.keys($map) {
    $output: list.append($output, $key + '');
  }
  @return $output;
}

// Shortcut to set an opacity for a CSS variable
@function color-opacity($hex, $opacity) {
  @return color-mix(in srgb, $hex $opacity, transparent);
}

// Display SVG as background image
@function svg-uri($width, $height, $svg) {
  $encoded: '';
  $slice: 2000;
  $index: 0;
  $svg: '<svg xmlns="http://www.w3.org/2000/svg" width="#{$width}" height="#{$height}" viewBox="0 0 #{$width} #{$height}">#{$svg}</svg>';
  $loops: math.ceil(calc(string.length($svg) / $slice));
  @for $i from 1 through $loops {
    $chunk: string.slice($svg, $index, $index + $slice - 1);
    $chunk: str-replace($chunk, '"', "'");
    $chunk: str-replace($chunk, '<', '%3C');
    $chunk: str-replace($chunk, '>', '%3E');
    $chunk: str-replace($chunk, '&', '%26');
    $chunk: str-replace($chunk, '#', '%23');
    $encoded: #{$encoded}#{$chunk};
    $index: $index + $slice;
  }
  @return url("data:image/svg+xml;charset=utf8,#{$encoded}");
}

// Replace string
@function str-replace($string, $search, $replace: '') {
  $index: string.index($string, $search);
  @if $index {
    @return string.slice($string, 1, $index - 1) + $replace + str-replace(string.slice($string, $index + string.length($search)), $search, $replace);
  }
  @return $string;
}

// Convert color to #HEX
@function to-hex($color) {
  $ie-hex: color.ie-hex-str($color);
  @return string.unquote('#' + string.slice($ie-hex, 4));
}

// Round a float number with precision
@function round-to($number, $precision: 3) {
  $factor: math.pow(10, $precision);
  @return math.div(math.round($number * $factor), $factor);
}

// Generate linear scale with clamp()
// From $min-size at $min-width to $max-size at $max-width
// https://clamp.font-size.app
@function clamp-builder($min-size, $max-size, $min-width, $max-width, $rem: 16px) {
  $min-size-rem: math.div($min-size, $rem);
  $max-size-rem: math.div($max-size, $rem);

  $slope: math.div($max-size - $min-size, $max-width - $min-width);
  $intersection: round-to(math.div(-$min-width * $slope + $min-size, $rem));
  $slope-vw: round-to($slope * 100);

  @return clamp(#{$min-size-rem}rem, #{$intersection}rem + #{$slope-vw}vw, #{$max-size-rem}rem);
}

@mixin focus-visible($color: var(--color-focus)) {
  outline-width: 3px;
  outline-offset: 2px;
  outline-style: solid;
  outline-color: $color;
}

@mixin required-sign($symbol: var(--field-required-symbol), $color: var(--field-required-color)) {
  color: $color;
  line-height: 0;
  font-size: 125%;
  content: $symbol;
  font-weight: normal;
  margin: 0 0 0 0.05em;
  vertical-align: middle;
}

%truncate-text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

%absolute-fill {
  inset: 0;
  position: absolute;
}

%flex-centered {
  display: flex;
  align-items: center;
  justify-content: center;
}
