@use "sass:list";
@use "sass:math";

@function mergeColorMaps($bulma-colors, $custom-colors) {
  // We return at least Bulma's hard-coded colors
  $merged-colors: $bulma-colors;

  // We want a map as input
  @if type-of($custom-colors) == "map" {
    @each $name, $components in $custom-colors {
      // The color name should be a string
      // and the components either a single color
      // or a colors list with at least one element
      @if type-of($name) ==
        "string" and
        (type-of($components) == "list" or type-of($components) == "color") and
        length($components) >=
        1
      {
        $color-base: null;
        $color-invert: null;
        $color-light: null;
        $color-dark: null;
        $value: null;

        // The param can either be a single color
        // or a list of 2 colors
        @if type-of($components) == "color" {
          $color-base: $components;
          $color-invert: bulmaFindColorInvert($color-base);
          $color-light: bulmaFindLightColor($color-base);
          $color-dark: bulmaFindDarkColor($color-base);
        } @else if type-of($components) == "list" {
          $color-base: list.nth($components, 1);

          // If Invert, Light and Dark are provided
          @if length($components) > 3 {
            $color-invert: list.nth($components, 2);
            $color-light: list.nth($components, 3);
            $color-dark: list.nth($components, 4);

            // If only Invert and Light are provided
          } @else if length($components) > 2 {
            $color-invert: list.nth($components, 2);
            $color-light: list.nth($components, 3);
            $color-dark: bulmaFindDarkColor($color-base);

            // If only Invert is provided
          } @else {
            $color-invert: list.nth($components, 2);
            $color-light: bulmaFindLightColor($color-base);
            $color-dark: bulmaFindDarkColor($color-base);
          }
        }

        $value: $color-base, $color-invert, $color-light, $color-dark;

        // We only want to merge the map if the color base is an actual color
        @if type-of($color-base) == "color" {
          // We merge this colors elements as map with Bulma's colors map
          // (we can override them this way, no multiple definition for the same name)
          // $merged-colors: map_merge($merged-colors, ($name: ($color-base, $color-invert, $color-light, $color-dark)))
          $merged-colors: map_merge(
            $merged-colors,
            (
              $name: $value,
            )
          );
        }
      }
    }
  }

  @return $merged-colors;
}

@function powerNumber($number, $exp) {
  $value: 1;

  @if $exp > 0 {
    @for $i from 1 through $exp {
      $value: $value * $number;
    }
  } @else if $exp < 0 {
    @for $i from 1 through -$exp {
      $value: math.div($value, $number);
    }
  }

  @return $value;
}

@function bulmaColorLuminance($color) {
  @if type-of($color) != "color" {
    @return 0.55;
  }

  $color-rgb: (
    "red": red($color),
    "green": green($color),
    "blue": blue($color),
  );

  @each $name, $value in $color-rgb {
    $adjusted: 0;
    $value: math.div($value, 255);

    @if $value < 0.03928 {
      $value: math.div($value, 12.92);
    } @else {
      $value: math.div($value + 0.055, 1.055);
      $value: powerNumber($value, 2);
    }

    $color-rgb: map-merge(
      $color-rgb,
      (
        $name: $value,
      )
    );
  }

  @return map-get($color-rgb, "red") * 0.2126 + map-get($color-rgb, "green") *
    0.7152 + map-get($color-rgb, "blue") * 0.0722;
}

@function bulmaFindColorInvert($color) {
  @if bulmaColorLuminance($color) > 0.55 {
    @return rgba(#000, 0.7);
  } @else {
    @return #fff;
  }
}

@function bulmaFindLightColor($color, $l: 96%) {
  @if type-of($color) == "color" {
    $l: 96%;

    @if lightness($color) > 96% {
      $l: lightness($color);
    }

    @return change-color($color, $lightness: $l);
  }

  @return $background;
}

@function bulmaFindDarkColor($color, $base-l: 29%) {
  @if type-of($color) == "color" {
    $luminance: bulmaColorLuminance($color);
    $luminance-delta: 0.53 - $luminance;
    $target-l: round($base-l + $luminance-delta * 53);

    @return change-color($color, $lightness: max($base-l, $target-l));
  }

  @return $text-strong;
}

@function bulmaRgba($color, $alpha) {
  @if type-of($color) != "color" {
    @return $color;
  }

  @return rgba($color, $alpha);
}

@function bulmaDarken($color, $amount) {
  @if type-of($color) != "color" {
    @return $color;
  }

  @return darken($color, $amount);
}

@function bulmaLighten($color, $amount) {
  @if type-of($color) != "color" {
    @return $color;
  }

  @return lighten($color, $amount);
}

@function bulmaColorBrightness($n) {
  $color-brightness: round(
   math.div((red($n) * 299) + (green($n) * 587) + (blue($n) * 114), 1000)
  );
  $light-color: round(
    math.div((red(#ffffff) * 299) + (green(#ffffff) * 587) + (blue(#ffffff) * 114), 1000)
  );

  @if abs($color-brightness) < math.div($light-color, 2) {
    @return "dark";
  }

  @return "bright";
}

@function bulmaEnoughContrast($foreground, $background) {
  $r: (max(red($foreground), red($background))) -
    (min(red($foreground), red($background)));
  $g: (max(green($foreground), green($background))) -
    (min(green($foreground), green($background)));
  $b: (max(blue($foreground), blue($background))) -
    (min(blue($foreground), blue($background)));
  $sum-rgb: $r + $g + $b;

  @if $sum-rgb < 500 {
    @return false;
  }

  @return true;
}

// By Cory Simmons https://corysimmons.com/
@function bulmaStringToNumber($value) {
  @if type-of($value) == "number" {
    @return $value;
  } @else if type-of($value) != "string" {
    $_: log("Value for `to-number` should be a number or a string.");
  }

  $result: 0;
  $digits: 0;
  $minus: str-slice($value, 1, 1) == "-";
  $numbers: (
    "0": 0,
    "1": 1,
    "2": 2,
    "3": 3,
    "4": 4,
    "5": 5,
    "6": 6,
    "7": 7,
    "8": 8,
    "9": 9,
  );

  @for $i from if($minus, 2, 1) through str-length($value) {
    $character: str-slice($value, $i, $i);

    @if not(index(map-keys($numbers), $character) or $character == ".") {
      @return to-length(if($minus, -$result, $result), str-slice($value, $i));
    }

    @if $character == "." {
      $digits: 1;
    } @else if $digits == 0 {
      $result: $result * 10 + map-get($numbers, $character);
    } @else {
      $digits: $digits * 10;
      $result: $result + map-get($numbers, $character) / $digits;
    }
  }

  @return if($minus, -$result, $result);
}
