/**
 * Font Presets
 * @note if $text-preset-value is set on 'inherit' make sure the 'default' $text-preset is set on the '<body>' element
 *
 * @require $text-preset
 * @require $font-families with cap-height set
 * @require $space-unit-sizes
 *
 * @param $font-size-value (inherit | string)
 * @param $line-height (list)
 * @param $set-align-classes (true | false | reset)
 *
 */

$class-align-baseline: '.align-baseline' !default;
$class-align-capline: '.align-capline' !default;
$class-align-median: '.align-median' !default;
$class-align-reset: '.align-reset' !default;
$class-fit: '.fit' !default;
$class-fit-up: '.fit-up' !default;
$class-fit-down: '.fit-down' !default;

// Short vars
$short-variable: (
	font-size: 'fs',
	line-height: 'lh',
	capheight: 'ch',
	xheight: 'xh',
	fit: 'fit',
	fit-up: 'fit-u',
	fit-down: 'fit-d',
);

/* Calculate font functions  */
@function calc-center($line-height, $font-size) {
	$center-correction: ($line-height - $font-size) / 2; //$line-height-value Minus default height of font-size Split by 2. So 1.5 becomes .5 split by two become .25

	@return $center-correction;
}

@function calc-capheight($font-size, $line-height, $font-cap-height) {
	// Calculate baseline and capline
	$font-correction: $font-size * ((1 - $font-cap-height )/ 2); // Split correction by 2 because only 50% of the alignments needs to be done
	$capheight-correction: calc-center($line-height, $font-size) + $font-correction;

	@return $capheight-correction;
}

@function calc-xheight($font-size, $line-height, $font-cap-height, $font-x-height) {
	$font-correction: $font-size * ((1 - $font-cap-height*$font-x-height )/ 2);
	$xheight-correction: calc-center($line-height, $font-size) + $font-correction;

	@return $xheight-correction;
}

/**
 * Space-text-preset-root
 * @description with space-text-preset-root variables for each text-preset will be set
 * @uses $text-presets
 * @param $set-text-preset
 */
@mixin space-text-preset-root($set-text-preset: default) {
	// Write back $set-text-preset to variable to keep original value
	$text-preset-value: $set-text-preset;

	@if ($set-text-preset == inherit) {
		$text-preset-value: default; // Set $set-text-preset-value to default to still set .align-baseline and .align-capline classes
	}

	// Get text-preset settings
	$text-preset: map-get($text-presets, $text-preset-value);

	// Set text-preset variables
	$font-size-list: map-get($text-preset, font-size);
	$line-height-list: map-get($text-preset, line-height);
	$font: default;

	// If font family is added to preset overwrite default
	@if (map-has-key($text-preset, font)) {
		$font: map-get($text-preset, font);
	}

	// Set default value for font-size
	$font-size: $font-size-list;

	@if (is-list($font-size-list)) {
		$font-size: nth($font-size-list, 1);
	}

	// Set default value for line-height
	$line-height: $line-height-list;

	@if (is-list($line-height-list)) {
		$line-height: nth($line-height-list, 1);
	}

	// Set default value for font-list
	$font-list: map-get($fonts, default);

	@if (is-list($font) == false) {
		$font-list: map-get($fonts, $font);
	} @else {
		@warn ('different fonts for each breakpoint is not yet supported');
	}

	// Set font settings
	$font-family: map-get($font-list, family);
	$font-cap-height: map-get($font-list, cap-height);
	$font-x-height: map-get($font-list, x-height);

	// Print font-family

	@each $viewport in $viewport-classes {
		$index: index($viewport-classes, $viewport);

		//@each $viewport, $set-text-preset-list in map-get($set-text-presets, $set-text-preset-value) {
		@include breakpoint($viewport) {
			// Set font-size for current breakpoint or fallback on font-size of previous breakpoint
			@if ($index <= length($font-size-list)) {
				$font-size: nth($font-size-list, $index);
			}
			// Set line-height for current breakpoint or fallback on line-height of previous breakpoint
			@if ($index <= length($line-height-list)) {
				$line-height: nth($line-height-list, $index);
			}

			// Check if $set-text-preset is a preset array
			// Get font-size
			$font-size-value: $font-size;

			// Calculate line-height
			$line-height-value: convert-space-units($line-height, $viewport);

			// Calculate baseline and capline
			$capheight-correction-value: calc-capheight($font-size-value, $line-height-value, $font-cap-height);

			// Calculate median
			$xheight-correction-value: calc-xheight($font-size-value, $line-height-value, $font-cap-height, $font-x-height);

			// Set font size
			#{set-var($text-preset-value, font-size)}: #{$font-size-value};

			// If line-height should be set
			@if ($line-height != false) {
				// Set line height
				#{set-var($text-preset-value, line-height)}: #{$line-height-value};
			}

			// Set translate for baseline correction
			@if ($capheight-correction-value != false) {
				// Add element to .align-baseline object
				#{set-var($text-preset-value, capheight)}: #{$capheight-correction-value};
			}

			@if ($xheight-correction-value != false) {
				// Add element to .align-xline object
				#{set-var($text-preset-value, xheight)}: #{$xheight-correction-value};
			}

			// Calculate fit corrections
			$su: map_get($space-unit-sizes, $viewport);
			$fit-value: $capheight-correction-value*-2;
			$fit-up-value: floor($fit-value / $su) * $su;
			$fit-down-value: ceil($fit-value / $su) * $su;

			#{set-var($text-preset-value, fit)}: #{$fit-value};
			#{set-var($text-preset-value, fit-up)}: #{$fit-up-value};
			#{set-var($text-preset-value, fit-down)}: #{$fit-down-value};
		}
	}
}

/**
 * Space text preset values
 */
@mixin space-text-preset-values($set-text-preset: default, $line-height: default, $set-align-classes: true) {
	// Write back $set-text-preset to variable to keep original value
	$text-preset-value: $set-text-preset;

	@if ($set-text-preset == inherit) {
		$text-preset-value: default; // Set $set-text-preset-value to default to still set .align-baseline and .align-capline classes
	}

	// Get text-preset settings
	$text-preset: map-get($text-presets, $text-preset-value);

	// Check validity of $text-preset
	@if ($text-preset != null) {
		/**
		 * GET VALUES
	     */

		// Set font-family
		$font: default;

		//// If font family is added to preset overwrite default
		@if (map-has-key($text-preset, font)) {
			$font: map-get($text-preset, font);
		}

		//// Set default value for font-list
		$font-list: map-get($fonts, default);

		@if (is-list($font) == false) {
			$font-list: map-get($fonts, $font);
		} @else {
			@warn ('different fonts for each breakpoint is not yet supported');
		}

		$font-family-value: map-get($font-list, family);

		// Set font-size
		$font-size-legacy-value: last(map-get($text-preset, font-size)); // Get highest value from font-size array
		$font-size-value: inherit;

		@if ($set-text-preset != inherit) {
			$font-size-value: #{get-var($text-preset-value, font-size)};
		}

		// Set line-height
		$line-height-value: inherit;

		@if ($set-text-preset != inherit) {
			$line-height-value: #{get-var($text-preset-value, line-height)};
		}

		// Set color
		$color-value: false;

		@if (map-has-key($text-preset, color)) {
			$color-value: #{map-get($text-preset, color)};
		}

		// Set font-weight
		$font-weight-value: false;

		@if (map-has-key($text-preset, font-weight)) {
			$font-weight-value: #{map-get($text-preset, font-weight)};
		}

		/**
		 * ASSIGN VALUES TO ATTRIBUTES
		 */

		// Print font-family
		@if ($font != default) {
			font-family: $font-family-value;
		}

		// Print font size
		@if space-legacy() {
			font-size: $font-size-legacy-value;
		}

		font-size: $font-size-value;

		// Print line height
		@if ($line-height != false) {
			line-height: $line-height-value;
		}

		// Print color
		@if ($color-value != false) {
			color: $color-value;
		}

		// Print font-weight
		@if ($font-weight-value != false) {
			font-weight: $font-weight-value;
		}

		// Set typography alignment classes
		@if ($set-align-classes == true) {
			// Add element to .align-baseline object
			@if (space-support(align-baseline)) {
				#{$class-align-baseline} & {
					// Set short variable
					--s: translateY(#{get-var($text-preset-value, capheight)});

					transform: var(--s);
				}
			}

			// Add element to .align-capline object
			@if (space-support(align-capline)) {
				#{$class-align-capline} & {
					// Set short variable
					--s: translateY(calc(#{get-var($text-preset-value, capheight)} * -1));

					transform: var(--s);
				}
			}

			@if (space-support(align-median)) {
				#{$class-align-median} & {
					// Set short variable
					--s: translateY(calc(#{get-var($text-preset-value, xheight)} * -1));

					transform: var(--s);
				}
			}

			@if (space-support(fit-baseline)) {
				#{$class-align-baseline} #{$class-fit} > &:first-child,
				#{$class-align-baseline}#{$class-fit} > &:first-child {
					margin-top: get-var($text-preset-value, fit);
				}
			}

			@if (space-support(fit-up-baseline)) {
				#{$class-align-baseline} #{$class-fit-up} > &:first-child,
				#{$class-align-baseline}#{$class-fit-up} > &:first-child {
					margin-top: get-var($text-preset-value, fit-up);
				}
			}

			@if (space-support(fit-down-baseline)) {
				#{$class-align-baseline} #{$class-fit-down} > &:first-child,
				#{$class-align-baseline}#{$class-fit-down} > &:first-child {
					margin-top: get-var($text-preset-value, fit-down);
				}
			}

			@if (space-support(fit-capline)) {
				#{$class-align-capline} #{$class-fit} > &:last-child,
				#{$class-align-capline}#{$class-fit} > &:last-child {
					margin-bottom: calc(#{get-var($text-preset-value, capheight)} * -2);
				}
			}

			@if (space-support(align-reset)) {
				#{$class-align-reset} & {
					transform: none;
				}
			}
		}
	} @else {
		@warn ('`' +$text-preset-value + '` is not present in your $text-presets');
	}
}

/*
 * Font preset mixin
 *
 * @example
 * @include text-preset(large) => font-size: 24rem; line-height: 3.2rem;
 *
 * @param $set-text-preset (array-key | inherit) string of array-key of $set-text-presets
 * @param $set-align-classes (true | false)
 */
@mixin text-preset($set-text-preset: default, $set-align-classes: true) {
	@include space-text-preset-values($set-text-preset, true, $set-align-classes);
}

/*
 * Self align mixin
 * @description aligns items based on default font-size to align-baseline, align-capline, align-median
 * without actually setting font-sizes, line-height or font-families
 */
@mixin self-align() {
	@include text-preset(inherit);
}

/*
 * Font-size function
 */
@mixin font-size($font-size-value: default) {
	@include space-text-preset-values($font-size-value, false, false);
}

/*
 * text-preset root variables
 *
 * @description this mixins creates root variables. Working from Edge 15+
 */
@mixin text-preset-variables() {
	:root {
		@each $text-preset, $value in $text-presets {
			@include space-text-preset-root($text-preset);
		}
	}
}

/*
 * Font-size-classes mixin
 *
 * @description this mixin adds classes for all the different font-sizes
 *
 * @example: font-size-small | font-size-default
 */

@mixin font-size-classes() {
	@each $size, $value in $text-presets {
		.font-size-#{$size} {
			@include font-size($size);
		}
	}
}

/*
 * text-preset-classes mixin
 *
 * @description this mixin adds classes for all the different text-presets
 * @example: text-preset-large | text-preset-xlarge
 */
@mixin text-preset-classes() {
	@each $text-preset, $value in $text-presets {
		.text-preset-#{$text-preset} {
			@include text-preset($text-preset);
		}
	}
}

/*
 * Legacy
 */
@mixin font-preset-variables() {
	@warn '`font-preset-variables` is a deprecated function since 1.0.0.alpha-5 use `text-preset-variables` instead';
	@warn 'Also note that `$font-presets` are replace with `$text-presets`';

	@include text-preset-variables();
}

@mixin font-preset-root() {
	@warn '`font-preset-root` is a deprecated function since 0.16 use `text-preset-variables` instead';

	@include text-preset-variables();
}

@mixin font-preset($set-text-preset: default, $set-align-classes: true) {
	@warn '`@include font-preset()` is a deprecated mixin since 1.0.0.alpha-5  use `@include text-preset()` instead';

	@include text-preset($set-text-preset, $set-align-classes);
}

@mixin font-preset-classes() {
	@warn '`@include font-preset-classes()` is a deprecated mixin since 1.0.0.alpha-5  use `@include text-preset-classes()` instead';

	@include text-preset-classes();
}
