/// Base styles for labels.
///
/// @output The output includes all styles for a basic label.
/// @example scss - Base label styles
///   @include _oLabelsBaseContent();
/// @access private
@mixin _oLabelsBaseContent() {
	@include oPrivateTypographySans(
		$scale: _oLabelsGet('font-scale'),
		$weight: 'semibold'
	);
	line-height: 1em;
	text-align: center;
	display: inline-block;
	box-sizing: border-box;
	margin: 0;
	text-decoration: none;
	padding: calc(
			#{_oLabelsGet('padding-vertical')} - #{_oLabelsGet('border-width')}
		)
		calc(#{_oLabelsGet('padding-horizontal')} - #{_oLabelsGet('border-width')});
	color: _oLabelsGet('text-color');
	background-color: _oLabelsGet('background-color');
	border: solid _oLabelsGet('border-width') transparent;
}

/// Size modifiers for labels.
///
/// @param {String} $size - The label size to output styles for. The valid sizes are `big` and `small`.
/// @output The output includes the `.o-labels--SIZE` modifier class definition, which includes all overrides.
/// @example scss - Big label styles
///   @include _oLabelsSize('big');
/// @access private
@mixin _oLabelsSize($size) {
	.o-labels--#{$size} {
		@include _oLabelsSizeContent($size);
	}
}

/// Add a state modifier for standard labels.
/// Note this mixin is dor standard labels only, not indicator labels.
///
/// @param {String|Map} $state-name - The standard label state to output styles for. See README for available states.
/// @param {Map} $opts [null] - A brand configuration which can be used to create custom standard label states. See README for more examples.
/// @output The output includes the `.o-labels--STATE` modifier class definition, which includes all overrides.
/// @example scss - Existing standard label state
///   @include oLabelsAddState('tier-gold');
/// @example scss - Custom standard label state
///   @include oLabelsAddState('citrus-fruit', (
///       background-color: oPrivateFoundationGet('o3-color-palette-lemon')
///   ));
/// @access public
@mixin oLabelsAddState($state-name, $opts: null) {
	// If we have a custom config, we use that instead of one of the
	// preconfigured states
	$variant: if($opts, $opts, $state-name);

	.o-labels--#{$state-name} {
		@include _oLabelsStandardStateContent($variant);
	}
}

/// Styles for a standard label without an `o-labels` CSS class.
/// Recommended only when a custom class name is required, for example within another component.
/// @output Styles for a label without a CSS selector.
/// @param {Map} $opts - A map containing a boolean to output base label styles, plus the label size and state (a state name or custom state map).
/// @example An existing label.
/// 	.o-example-my-label {
/// 		@include oLabelsContent($opts: ('base': true, 'size': 'big', 'state': 'tier-gold'));
/// 	}
/// @example A custom label.
/// 	.o-example-my-custom-label {
/// 		@include oLabelsContent($opts: (
/// 			'base': true,
/// 			'size': 'big',
/// 			'state': (
/// 				'background-color': oPrivateFoundationGet('o3-color-palette-lemon')
/// 			)
/// 		));
/// 	}
/// @access public
@mixin oLabelsContent($opts: ()) {
	$base: map-get($opts, 'base');
	$size: map-get($opts, 'size');
	$state: map-get($opts, 'state');

	@if $base {
		@include _oLabelsBaseContent();
	}

	@if $state {
		@include _oLabelsStandardStateContent($state);
	}

	@if $size {
		@include _oLabelsSizeContent($size);
	}
}

/// Styles for a timestamp label i.e. .o-labels-timestamp.
/// This mixin is not recommend. Instead the the `oLabels` primary mixin and
/// o-labels markup. This should only be used where using o-labels markup is
/// not possible.
///
/// @example Output a timestamp label with custom markup.
///    .my-timestamp-label {
///        @include oLabelsTimestampContent();
///    }
/// @access public
@mixin oLabelsTimestampContent() {
	@extend %_o-labels-timestamp;
}

/// Styles for indicator label elements e.g. .o-labels-indicator.
/// This mixin is not recommend. Instead the the `oLabels` primary mixin and
/// o-labels markup. This should only be used where using o-labels markup is
/// not possible.
/// @example Output indicator labels with custom markup.
///    .my-indicator-label {
///        @include oLabelsIndicatorContent($opts: ('block': true));
///    }
///    .my-indicator-label--new {
///        @include oLabelsIndicatorContent($opts: ('block': true, 'modifier': 'new'));
///    }
///    .my-indicator-label--updated {
///        @include oLabelsIndicatorContent($opts: ('block': true, 'modifier': 'updated'));
///    }
///    .my-indicator-label--closed {
///        @include oLabelsIndicatorContent($opts: ('block': true, 'modifier': 'closed'));
///    }
///    .my-indicator-label--live {
///        @include oLabelsIndicatorContent($opts: ('block': true, 'modifier': 'live'));
///    }
///    .my-indicator-label__status {
///        @include oLabelsIndicatorContent($opts: ('element': 'status'));
///    }
///    .my-indicator-label__timestamp {
///        @include oLabelsIndicatorContent($opts: ('element': 'timestamp'));
///    }
/// @param {Sting|Map} $ops - the BEM element to output styles for, see example.
/// @access public
@mixin oLabelsIndicatorContent($opts: ()) {
	$modifier: map-get($opts, 'modifier');
	$element: map-get($opts, 'element');
	$block: map-get($opts, 'block');
	// Validate element.
	// The timestamp element .o-labels-indicator__timestamp element
	// currently has no styles but may do in the future.
	$valid-elements: ('status', 'timestamp');
	@if $element and not index($valid-elements, $element) {
		@error 'Element must be one of "#{$valid-elements}" if set. "#{$element}" given.';
	}
	// Output block "base" styles i.e .o-labels-indicator
	@if $block and not $modifier {
		@extend %_o-labels-indicator;
	}
	// Output modifier styles e.g .o-labels-indicator--live
	@if $block and $modifier {
		@include _oLabelsIndicatorStatusContent($modifier);
	}
	// Output status element styles i.e .o-labels-indicator__status
	@if $element == 'status' {
		@extend %_o-labels-indicator__status;
	}
}

/// Styles to change the size of a standard label.
/// @param {Sting} $size - The label size to output styles for. The valid sizes are `big` and `small`.
/// @access private
@mixin _oLabelsSizeContent($size) {
	$scale: _oLabelsGet('font-scale', $size);
	@if $scale {
		@include oPrivateTypographySans($scale);
		line-height: 1;
	}
	padding: calc(
			#{_oLabelsGet('padding-vertical', $size)} - #{_oLabelsGet('border-width')}
		)
		calc(
			#{_oLabelsGet('padding-horizontal', $size)} - #{_oLabelsGet(
					'border-width'
				)}
		);
}

/// Styles for a state.
/// @param {Sting|Map} $variant - An existing state name or a custom state map.
/// @access private
@mixin _oLabelsStandardStateContent($variant) {
	background-color: _oLabelsGet('background-color', $variant);
	border-color: _oLabelsGet('border-color', $variant);
	text-transform: _oLabelsGet('text-transform', $variant);

	// Set text colour or calculate based on background
	@if _oLabelsGet('text-color', $variant) {
		color: _oLabelsGet('text-color', $variant);
	} @else {
		color: oPrivateColorsGetTextColor(
			_oLabelsGet('background-color', $variant),
			100
		);
	}

	// Set the spacing
	@if _oLabelsGet('padding-vertical', $variant) and
		_oLabelsGet('padding-horizontal', $variant)
	{
		padding: calc(
				#{_oLabelsGet('padding-vertical', $variant)} -
					#{_oLabelsGet('border-width')}
			)
			calc(
				#{_oLabelsGet('padding-horizontal', $variant)} -
					#{_oLabelsGet('border-width')}
			);
	}
}

/// Styles for indicator label statuses.
/// @param {Sting} $status - An existing indicator status e.g. live, closed, new, updated
/// @access private
@mixin _oLabelsIndicatorStatusContent($status) {
	@if not index($_o-labels-indicator-status, $status) {
		@error '"#{$status}" is not an indicator label status. ' +
			'Expected one or more of the following statuses: #{$_o-labels-indicator-status}.';
	}
	// All indicator labels currently use the same colour except the "closed".
	// It is not possible to customise indicator labels currently but this
	// may be added in the future, e.g. for the internal brand:
	// https://github.com/Financial-Times/o-labels/issues/58
	@if $status == 'closed' {
		@extend %_o-labels-indicator-closed-color;
	} @else {
		@extend %_o-labels-indicator-live-color;
	}
	@extend %_o-labels-timestamp-typography;

	@if ($status == 'live') {
		& > %_o-labels-indicator__status:before {
			animation: _o-labels-live-pulse 1.2s ease-in-out infinite;
			// Prevent animation of the live label if the reader has indicated
			// that they prefer reduced motion. This may be conservative but
			// as the live indicator is presented alongside content (including
			// the front page at the time of writing) we do not want to risk
			// severely distracting some readers.
			// https://www.w3.org/WAI/WCAG21/Understanding/pause-stop-hide.html
			@media (prefers-reduced-motion) {
				animation: none;
			}
		}

		// output keyframes once when live status is output
		@if ($status == 'live' and $_o-labels-indicator-live-pulse-output: false) {
			$_o-labels-indicator-live-pulse-output: true !global;
			@keyframes _o-labels-live-pulse {
				0% {
					opacity: 1;
				}
				30% {
					opacity: 0.4;
				}
				70% {
					opacity: 0.4;
				}
				100% {
					opacity: 1;
				}
			}
		}
	}
}
