/// Output styles for page headings.
/// @example Output heading level 1 styles.
///     h1 {
///     	@include oTypographyHeading($level: 1);
///     }
/// @example Output heading level 5 styles.
///     h5 {
///     	@include oTypographyHeading($level: 5);
///     }
/// @param {Number} $level - The heading level 1-5.
@mixin oTypographyHeading($level) {
	$headings: (
		'heading-level-one',
		'heading-level-two',
		'heading-level-three',
		'heading-level-four',
		'heading-level-five',
		'heading-level-six',
	);

	@if(type-of($level) != 'number' or $level < 1 or $level > 6) {
		@error 'Heading level must be a Number 1-6. Found #{inspect($level)}.';
	}

	$from: nth($headings, $level);

	// Get heading styles from brand config (see _brand.scss)
	// If weight is not given default to regular, to override browser defaults.
	$weight: _oTypographyGet('weight', $from);
	$weight: if($weight, $weight, 'regular');
	@include oTypographySans(
		$scale: (
			default: _oTypographyGet('scale', $from),
			S: _oTypographyGet('scale-s', $from),
			M: _oTypographyGet('scale-m', $from),
			L: _oTypographyGet('scale-l', $from),
			XL: _oTypographyGet('scale-xl', $from)
		),
		$weight: $weight
	);
	color: oColorsByUsecase('body', 'text', $fallback: null);
	margin: 0 0 oSpacingByName('s4');
}


/// Body text styles
@mixin oTypographyBody($theme: '') {
	@include oTypographySans(1);
	margin: 0 0 oSpacingByName('s6');
	$variant: if($theme, 'body-#{$theme}', 'body');
	color: var(--_o-typography-body-color, #{_oTypographyGet('color', $variant)});
}

/// Subscript text
@mixin oTypographySub {
	// make subscript smaller and sans-serif
	// 12px given 18px copy
	@include oTypographySans();
	font-size: 0.666em;
	// override o-normalise default
	position: static;
	vertical-align: sub;
	line-height: 0;
	// prevent sub increasing line-height
	display: inline-block;
	margin-bottom: -1em;
}

/// Superscript text
@mixin oTypographySuper {
	// make superscript smaller and sans-serif
	// 12px given 18px copy
	@include oTypographySans();
	font-size: 0.666em;
	// override o-normalise default
	position: static;
	vertical-align: super;
	line-height: 0;
	// prevent super increasing line-height
	display: inline-block;
	margin-top: -1em;
}

/// Output link styles.
///
/// @example Output the styles for a standard link.
///     .my-link {
///     	@include oTypographyLink();
///     }
///
/// @example Output a custom, claret coloured link to go on the default background colour (paper for the core brand, white otherwise).
///     .my-claret-link {
///     	@include oTypographyLink($theme: (
///     		'base': 'claret',
///     		'hover': 'claret-30',
///     	));
///     }
///
/// @example Output a custom, lemon coloured link to go on a slate background.
///     .my-inverse-link {
///     	@include oTypographyLink($theme: (
///     		'base': 'lemon',
///     		'hover': 'lemon-30',
///     		'context': 'slate',
///     	));
///     }
///
/// @param {Boolean} $external [false] - This parameter is deprecated - we no longer output an icon for external links
/// @param {Map|String|Null} $theme [null] - A custom theme to change the look of a link, with colours for properties `base` (the main link colour), `hover` (the links over colour), and optional `context` key. Context is the colour the link will be placed on, it defaults to the page background (paper for the core brand, white otherwise).
/// @param {Boolean} $include-base-styles [true] - If set to false standard link styles will not be output, only additional styles required by a custom theme.
@mixin oTypographyLink($external: false, $theme: null, $include-base-styles: true) {
	// stylelint-disable declaration-block-no-duplicate-properties -- to provide a css custom property fallback
	// Default link colours.
	// These may be `null` if the usecase is not set, i.e. for the whitelabel brand.
	$theme: if($theme, $theme, 'link');
	$base-color: oColorsByUsecase(link, text, $fallback: null);
	$hover-color: oColorsByUsecase(link-hover, text, $fallback: null);
	$context-color: oColorsByUsecase(page, background);
	$underline-size: 0.25ex; // 2px for 18px MetricWeb

	// Map themes to less friendly o-brand variant
	$theme: if($theme == 'inverse', 'link-inverse', $theme);
	$theme: if($theme == 'professional', 'link-professional', $theme);
	$theme: if($theme == 'professional-inverse', 'link-professional-inverse', $theme);
	$theme: if($theme == 'ft-live', 'link-ft-live', $theme);

	// Get custom base colour.
	$theme-base: _oTypographyGet('base', $theme);
	$base-color: if(type-of($theme-base) == 'string', oColorsByName($theme-base), $theme-base);
	// Get custom hover colour.
	$theme-hover: _oTypographyGet('hover', $theme);
	$hover-color: if(type-of($theme-hover) == 'string', oColorsByName($theme-hover), $theme-hover);
	// Get optional context colour.
	$theme-context: _oTypographyGet('context', $theme);
	@if $theme-context {
		$context-color: if(type-of($theme-context) == 'string', oColorsByName($theme-context), $theme-context);
	}
	// Validate colours given.
	@if(type-of($theme) == 'map' and type-of($base-color) != 'color') {
		@error 'A custom link theme must have a `base` property with a colour or palette colour name e.g. `claret`. But found #{$theme-base}.';
	}
	@if(type-of($theme) == 'map' and type-of($hover-color) != 'color') {
		@error 'A custom link theme must have a `hover` property with a color or palette colour name e.g. `claret`. But found #{$theme-hover}.';
	}
	@if(type-of($theme) == 'map' and $theme-context and type-of($context-color) != 'color') {
		@error 'A custom link theme may optionally have a `context` property with a color or palette colour name, to indicate the colour of the page behind the link, e.g. `null` or `paper`. But found #{$theme-context}.';
	}

	@if ($external) {
		@warn 'The $external parameter for oTypographyLink is deprecated. ' +
			'Remove the $external argument from the oTypographyLink include. ' +
			'During an accessibility audit we found that the icon was causing confusion ' +
			'as some users understood the icon to mean the link will open in a new window. ' +
			'After discussing with the Design team and looking into what websites such as gov.uk do, ' +
			'we decided to remove the icon for external links.';
	}

	&[target="_blank"] {
		// Visually hidden content is positioned absolutely. Position relative on the anchor means the hidden
		// content is positioned relative to the anchor element. This ensures it is clipped by the overflow
		// property of an ancestor; otherwise the pseudo element which contains the hidden content will not
		// be clipped by the overflow of any ancestor between it and its containing block.
		// https://drafts.csswg.org/css2/#visufx
		position: relative;
		&:after {
			@include oNormaliseVisuallyHidden();
			content: '(opens a new window)';
		}
	}

	// Output base styles shared by all links.
	@if($include-base-styles) {
		text-decoration: none;
		cursor: pointer;
		border-bottom: $underline-size solid;

		@supports (text-decoration-thickness: $underline-size) {
			border-bottom: 0;
			text-decoration-thickness: $underline-size; //sass-lint:disable-line no-misspelled-properties
			text-decoration-line: underline;
		}
	}

	// Output base styles shared by all links, or
	// required for a custom link theme.
	@if($include-base-styles or $theme) {
		color: $base-color;
		color: var(--_o-typography-link-color, #{$base-color});
		$default-decoration-color: if($base-color, oColorsMix($base-color, $context-color, $percentage: 20), null);
		$theme-decoration-color: _oTypographyGet('base-decoration', $theme);
		$decoration-color: if($theme-decoration-color, $theme-decoration-color, $default-decoration-color);
		border-bottom-color: $decoration-color;
		border-bottom-color: var(--_o-typography-link-decoration-color, #{$decoration-color});
		text-decoration-color: $decoration-color;
		text-decoration-color: var(--_o-typography-link-decoration-color, #{$decoration-color});
	}

	&:hover {
		@if($include-base-styles or $theme) {
			color: $hover-color;
			color: var(--_o-typography-link-color-hover, #{$hover-color});
			$default-decoration-color: if($base-color, oColorsMix($base-color, $context-color, $percentage: 40), null);
			$theme-decoration-color: _oTypographyGet('hover-decoration', $theme);
			$decoration-color: if($theme-decoration-color, $theme-decoration-color, $default-decoration-color);
			border-bottom-color: $decoration-color;
			border-bottom-color: var(--_o-typography-link-decoration-color-hover, #{$decoration-color});
			text-decoration-color: $decoration-color;
			text-decoration-color: var(--_o-typography-link-decoration-color-hover, #{$decoration-color});
		}
	}

	// o-normalise provides extra focus styles for links
	&:focus {
		@if($include-base-styles) {
			border-bottom-color: transparent;
			text-decoration-color: transparent;
		}
		@if($include-base-styles or $theme) {
			color: $hover-color;
			color: var(--_o-typography-link-color-hover, #{$hover-color});
		}
	}
	// stylelint-enable declaration-block-no-duplicate-properties -- to provide a css custom property fallback
}

/// Output styles for lists.
/// Styles child `li` elements. Apply to a
/// containing list element such as `ul` or `ol`.
/// Does not output font styles, these are
/// inherited (@see oTypographyBody).
///
/// @example Output the styles for an unordered list.
///     .my-unordered-list {
///     	@include oTypographyList('unordered');
///     }
///
/// @example Output the styles for an ordered and unordered list, sharing base list styles.
///     .my-list {
///     	@include oTypographyList();
///     }
///
///     .my-list--ordered {
///     	@include oTypographyList('ordered', $include-base-styles: false);
///     }
///
///     .my-list--unordered {
///     	@include oTypographyList('unordered', $include-base-styles: false);
///     }
///
/// @param {String|Null} $type [null] - "ordered", "unordered", or null for just the base styles shared by all lists
/// @param {Boolean} $include-base-styles [true] - set to false to exclude base styles which are shared by all list types
@mixin oTypographyList($type: null, $include-base-styles: true) {
	// Undo browser defaults.
	@if($include-base-styles) {
		margin: 0 0 oSpacingByName('s6');
		padding: 0;
		list-style: none;
	}
	// Reset number counter for new ordered list.
	@if($type == 'ordered') {
		counter-reset: item;
	}
	> li {
		@if($include-base-styles) {
			position: relative;
			// Undo browser default.
			margin: 0;
			// Allow space for 2-3 numbers for both ordered and unordered lists,
			// so content aligns between both list types.
			padding-left: calc(2ch + #{oSpacingByName('s1')});
		}
		&:before {
			@if($include-base-styles) {
				@include oTypographySans();
				display: inline-block;
				position: absolute;
				left: 0;
				transform-origin: center left;
			}

			@if($type == 'unordered') {
				content: '\2022'; // dot character
				color: inherit;
				// 28px marker given a parent font-size of 18px
				transform: scale(#{div(28, 18)});
				// magic number to center marker
				margin-top: #{div(28, 18) * -0.16ch};
			}

			@if($type == 'ordered') {
				@include oTypographySans($weight: 'semibold', $include-font-family: false);
				content: counter(item);
				counter-increment: item;
				font-feature-settings: "tnum";
				// 16px marker given a parent font-size of 18px
				transform: scale(#{div(16, 18)});
				// magic number to make marker flush to the left
				margin-left: #{div(16, 18) * -0.16ch};
			}
		}
	}
}

/// Style for <footer> tags
@mixin oTypographyFooter {
	@include oTypographySans($scale: 1, $line-height: 24px);
	color: oColorsByUsecase('body', 'text', $fallback: null);
}

/// Styles for photo or video credit/caption
@mixin oTypographyCaption {
	@include oTypographySans($scale: -1);
	margin-top: oSpacingByName('s2');
	margin-bottom: 0;
	color: oColorsByUsecase('body', 'text', $fallback: null);
}
