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

@function color-hue($color) {
	@return color.channel($color, 'hue', $space: hsl);
}

@function color-saturation($color) {
	@return color.channel($color, 'saturation', $space: hsl);
}

@function color-lightness($color) {
	@return color.channel($color, 'lightness', $space: hsl);
}

@function color-alpha($color) {
	@return color.channel($color, 'alpha');
}

@function color-hsla($color) {
	@return hsla(
		color-hue($color),
		color.channel($color, 'saturation', $space: hsl),
		color.channel($color, 'lightness', $space: hsl),
		color.channel($color, 'alpha')
	);
}

@function color-red($color) {
	@return color.channel($color, 'red', $space: rgb);
}

@function color-green($color) {
	@return color.channel($color, 'green', $space: rgb);
}

@function color-blue($color) {
	@return color.channel($color, 'blue', $space: rgb);
}

@function hsla-map($color, $name, $noVarExport: false) {
	@if $noVarExport {
		@return (
			#{$name}: hsla(color-hue($color), color.channel($color, 'saturation', $space:
							hsl), color.channel($color, 'lightness', $space: hsl), color.channel($color, 'alpha'))
		);
	} @else {
		@return (
			hue: color-hue($color),
			saturation: color.channel($color, 'saturation', $space: hsl),
			lightness: color.channel($color, 'lightness', $space: hsl),
			#{$name}: hsla(var(--color-#{$name}-hue), var(--color-#{$name}-saturation), var(--color-#{$name}-lightness), color.channel($color, 'alpha'))
		);
	}
}

@function alpha-color($color, $name, $alpha, $noVarExport) {
	@if $noVarExport {
		@return (
			hsla(
				color-hue($color),
				color.channel($color, 'saturation', $space: hsl),
				color.channel($color, 'lightness', $space: hsl),
				$alpha
			)
		);
	} @else {
		@return hsla(
			var(--color-#{$name}-hue),
			var(--color-#{$name}-saturation),
			var(--color-#{$name}-lightness),
			$alpha
		);
	}
}

@function hex-to-rgb($hex) {
	@return color.channel($hex, 'red', $space: rgb),
		color.channel($hex, 'green', $space: rgb),
		color.channel($hex, 'blue', $space: rgb);
}

@function color-alpha-map(
	$color,
	$name,
	$steps: 9,
	$scale: 0.1,
	$noVarExport: false
) {
	$result: hsla-map($color, $name, $noVarExport);

	@for $index from 1 to ($steps + 1) {
		$result: map.merge(
			$result,
			(
				#{$index}:
					alpha-color($color, $name, $index * $scale, $noVarExport)
			)
		);
	}

	@return $result;
}

@function color-shades-map(
	$color,
	$name,
	$steps: 5,
	$scale: 10%,
	$fixed: false,
	$noVarExport: false
) {
	$result: map.merge(
		map.set(
			color-lighten-map(
				$color,
				$name,
				$steps,
				$scale,
				'lighten',
				$fixed,
				$noVarExport
			),
			$name,
			$color
		),
		color-darken-map(
			$color,
			$name,
			$steps,
			$scale,
			'darken',
			$fixed,
			$noVarExport
		)
	);

	@return $result;
}

@function color-lighten-map(
	$color,
	$name,
	$steps: 5,
	$scale: 10%,
	$prefix: '',
	$fixed: false,
	$noVarExport: false,
	$inverted: true
) {
	$result: hsla-map($color, $name, $noVarExport);

	@for $counter from 1 to ($steps + 1) {
		$index: $counter;

		@if $inverted {
			$index: $steps + 1 - $counter;
		}

		$key: $index;

		@if $prefix != '' {
			$key: $prefix + '-' + $index;
		}

		@if $fixed {
			$increment: $scale * $index;

			@if $noVarExport {
				$alpha: color.channel($color, 'lightness', $space: hsl) +
					$increment;
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsla(
								color-hue($color),
								color.channel(
									$color,
									'saturation',
									$space: hsl
								),
								color.channel($color, 'lightness', $space: hsl),
								$alpha
							)
					)
				);
			} @else {
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsl(
								var(--color-#{$name}-hue)
									var(--color-#{$name}-saturation)
									calc(
										var(--color-#{$name}-lightness) +
											#{$increment}
									)
							)
					)
				);
			}
		} @else {
			$increment: math.div($scale * $index, 100);
			$increment: math.div($increment, ($increment * 0 + 1));
			$increment: $increment + 1;

			@if $noVarExport {
				$alpha: color.channel($color, 'lightness', $space: hsl) *
					$increment;
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsla(
								color-hue($color),
								color.channel(
									$color,
									'saturation',
									$space: hsl
								),
								color.channel($color, 'lightness', $space: hsl),
								$alpha
							)
					)
				);
			} @else {
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsl(
								var(--color-#{$name}-hue)
									var(--color-#{$name}-saturation)
									calc(
										var(--color-#{$name}-lightness) *
											#{$increment}
									)
							)
					)
				);
			}
		}
	}

	@return $result;
}

@function color-darken-map(
	$color,
	$name,
	$steps: 5,
	$scale: 10%,
	$prefix: '',
	$fixed: false,
	$noVarExport: false,
	$inverted: false
) {
	$result: hsla-map($color, $name, $noVarExport);

	@for $counter from 1 to ($steps + 1) {
		$index: $counter;

		@if $inverted {
			$index: $steps + 1 - $counter;
		}

		$key: $index;

		@if $prefix != '' {
			$key: $prefix + '-' + $index;
		}

		@if $fixed {
			$decrement: $scale * $index;

			@if $noVarExport {
				$alpha: color.channel($color, 'lightness', $space: hsl) -
					$decrement;
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsla(
								color-hue($color),
								color.channel(
									$color,
									'saturation',
									$space: hsl
								),
								color.channel($color, 'lightness', $space: hsl),
								$alpha
							)
					)
				);
			} @else {
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsl(
								var(--color-#{$name}-hue)
									var(--color-#{$name}-saturation)
									calc(
										var(--color-#{$name}-lightness) -
											#{$decrement}
									)
							)
					)
				);
			}
		} @else {
			$decrement: math.div($scale * $index, 100);
			$decrement: math.div($decrement, ($decrement * 0 + 1));
			$decrement: 1 - $decrement;

			@if $noVarExport {
				$alpha: color.channel($color, 'lightness', $space: hsl) *
					$decrement;
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsla(
								color-hue($color),
								color.channel(
									$color,
									'saturation',
									$space: hsl
								),
								color.channel($color, 'lightness', $space: hsl),
								$alpha
							)
					)
				);
			} @else {
				$result: map.merge(
					$result,
					(
						#{$key}:
							hsl(
								var(--color-#{$name}-hue)
									var(--color-#{$name}-saturation)
									calc(
										var(--color-#{$name}-lightness) *
											#{$decrement}
									)
							)
					)
				);
			}
		}
	}

	@return $result;
}

@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;
}

@function str-split($string, $separator) {
	$split-arr: ();
	$index: string.index($string, $separator);

	@while $index != null {
		$item: string.slice($string, 1, $index - 1);
		$split-arr: list.append($split-arr, $item);
		$string: string.slice($string, $index + 1);
		$index: string.index($string, $separator);
	}

	$split-arr: list.append($split-arr, $string);

	@return $split-arr;
}

@function list-to-string($list, $glue: ', ') {
	$result: null;

	@for $i from 1 through list.length($list) {
		$e: list.nth($list, $i);

		@if $result and $e {
			$result: $result + $glue + $e;
		} @else if $e {
			$result: $e;
		}
	}

	@return $result;
}
