@use "sass:map";
@use "sass:color";
@use "sass:math";
@use "sass:string";
@use "./type-checking" as check;
@use "../helpers" as helpers;

$is-test: false !default;

/// Convert HEX colors to R, G, B values
/// @param {Color} $color
/// @return {String}
/// @group Color
/// @author Felix Scholze
/// @since v1.5.0
@function hex-to-rgb-values($color) {
  @return color.channel($color, 'red', $space: rgb) + ", " + color.channel($color, 'green', $space: rgb) + ", " + color.channel($color, 'blue', $space: rgb);
}

/// Convert HEX colors to RGB (space-separated values)
/// @param {Color} $color - HEX color
/// @param {Number} $alpha - Alpha
/// @return {String}
/// @group Color
/// @author Felix Scholze
/// @since v1.5.0
@function hex-to-rgb($color, $alpha: false) {
  @return string.unquote("rgb") + "(" + (color.channel($color, 'red', $space: rgb) color.channel($color, 'green', $space: rgb) color.channel($color, 'blue', $space: rgb)) + if($alpha, " / " + $alpha, "") + ")";
}

/// Generate shades in light and dark from a base color.
/// The base color is the starting point, light shades starting from 100, dark shades following when the light shades are finished.
///
/// @param {Color} $base-color - Base color
/// @param {Number} $num-shades [5] - Number of shades to generate
/// @param {Number} $lighten-percent [0.5] - Percent (in decimal places from 0 to 1) to lighten each shade
/// @param {Number} $darken-percent [0.5] - Percent (in decimal places from 0 to 1) to darken each shade
/// @param {String} $color-key-name ["color"] - Key name for the base color
/// @param {String} $color-key-separator ["-"] - Key separator for the base color
/// @return {Map}
/// @group Color
/// @author Felix Scholze
/// @since v2.4.0
///
/// @example
///    @debug generate-color-shades(#d33030, 5, 0.5, 0.5, "red");
///
/// @example CSS - Output CSS
///    ("red-500": #d74545, "red-400": #dc5a5a, "red-300": #e06f6f, "red-200": #e58484, "red-100": #e99999, "red": #d33030, "red-600": #c12929, "red-700": #ac2424, "red-800": #972020, "red-900": #811c1c, "red-1000": #6c1717)
///
@function generate-color-shades(
  $base-color,
  $num-shades: 5,
  $lighten-percent: 0.5,
  $darken-percent: 0.5,
  $color-key-name: "color",
	$color-key-separator: "-",
) {
  $shades: ();

  /// Generate shades for light mode
  @for $i from 1 through $num-shades {
    $shade: color.adjust(
      $base-color,
      $lightness: calc((100% / ($num-shades * 2)) * $i * $lighten-percent)
    );
    $shades: map.merge($shades, ($color-key-name + $color-key-separator + (($num-shades + 1) - $i) * 100: $shade));
  }

  $shades: map.merge(
    $shades,
    (
      $color-key-name: $base-color,
    )
  );

  /// Generate shades for dark mode
  @for $i from 1 through $num-shades {
    $shade: color.adjust(
      $base-color,
      $lightness: calc((100% / ($num-shades * 2)) * $i * -1 * $darken-percent)
    );
    $shades: map.merge($shades, ($color-key-name + $color-key-separator + ($i + $num-shades) * 100: $shade));
  }

  @return $shades;
}

/// Generate a map of colors that are mixed between three colors with a peak point for color2.
/// @param {Color} $color1 - The first color.
/// @param {Color} $color2 - The second color.
/// @param {Color} $color3 - The third color.
/// @param {Number} $steps [20] - The number of steps to generate.
/// @param {Number} $color2-peak [11] - The peak point for color2.
/// @return {Map} - The map of colors.
/// @group Color
/// @author https://github.com/red-freak
/// @since v2.5.0
///
/// @example
///    @debug generate-mixed-colors(green, yellow, red, 7, 4);
///
/// @example CSS - Output CSS
///    (1: green, 2: #80c000, 3: #bfdf00, 4: yellow, 5: #ffaa00, 6: #ff5500, 7: red)
///
@function generate-mixed-colors(
	$color1,
	$color2,
	$color3,
	$steps: 20,
	$color2-peak: 11,
) {
	@if check.is-color($color1) == false {
		@return helpers.error("❌  ===> The color1 parameter must be a color.", $catch: $is-test);
	}
	@if check.is-color($color2) == false {
		@return helpers.error("❌  ===> The color2 parameter must be a color.", $catch: $is-test);
	}
	@if check.is-color($color3) == false {
		@return helpers.error("❌  ===> The color3 parameter must be a color.", $catch: $is-test);
	}
	@if check.is-integer($steps) == false {
		@return helpers.error("❌  ===> The steps parameter must be an integer.", $catch: $is-test);
	}
	@if check.is-integer($color2-peak) == false {
		@return helpers.error("❌  ===> The color2-peak parameter must be an integer.", $catch: $is-test);
	}
	@if $color2-peak > $steps {
		@return helpers.error("❌  ===> The peak point for color2 must be less than or equal to the number of steps.", $catch: $is-test);
	}
	@if  $color2-peak < 1 {
		@return helpers.error("❌  ===> The peak point for color2 must be greater than or equal to 1.", $catch: $is-test);
	}

	$color-map: (1: $color1);

	@if $color2-peak > 2 {
		@for $i from 2 through $color2-peak - 1 {
			$percentage: (math.div(1, $color2-peak) * ($color2-peak - $i));
			$color: color.mix($color1, $color2, $percentage * 100%);
			$color-map: map.merge($color-map, ($i: $color));
		}
	}

	$color-map: map.merge($color-map, ($color2-peak: $color2));

	@if $color2-peak < $steps {
		@for $i from $color2-peak + 1 through $steps - 1 {
			$percentage: (math.div(1, $steps - $color2-peak) * ($steps - $i));
			$color: color.mix($color2, $color3, $percentage * 100%);
			$color-map: map.merge($color-map, ($i: $color));
		}

		$color-map: map.merge($color-map, ($steps: $color3))
	}

	@return $color-map;
}