
/// Gets the value of a component variable for the current brand.
/// If multiple variables are requested they are concatenated.
///
/// @example scss
///     @oBrandGet($component: 'o-component', $variables: ('example-border-size', 'example-border-style', 'example-border-color')); // 1px solid red
/// @example scss
///     @oBrandGet($component: 'o-component', $variables: 'example-color'); // black
/// @example scss
///     @oBrandGet($component: 'o-component', $variables: 'example-color', $from: 'inverse'); // white
/// @example scss
///     @oBrandGet($component: 'o-component', $variables: 'example-color', $from: (example-color: yellow)); // yellow
///
/// @access public
/// @param {string} $component
/// @param {string | list} $variables
/// @param {map|string} $from Get variable values from a defined brand variant or from a map of variables.
/// @return {string | number | color | bool | null}
///
@function oBrandGet($component, $variables, $from: null) {
	// Validate component name.
	$validated-component-name: _oBrandValidateName('Component', $component, 'Cannot get variable(s) "#{$variables}" for component "#{$component}"');
	// Validate variant name if getting the variables from a pre-defined variant.
	@if type-of($from) != 'map' and type-of($from) != 'null' {
		$validated: _oBrandValidateName(
			'Variant',
			$from,
			'Get variables "#{$variables}" for "#{$component}" from "#{inspect($from)}"'
		);
	}
	// Validate names of the variables we are trying to get.
	@each $variable-name in $variables {
		$validated-variable-names: _oBrandValidateName(
			'Variable',
			$variable-name,
			'Cannot get variable "#{$variable-name}" for component "#{$component}" from variant "#{inspect($from)}"'
		);
	}
	// If from default component variables or a pre-defined variant.
	@if type-of($from) == 'string' or type-of($from) == 'null' {
		// A brand must be configured before o-brand can be used.
		$brand: _oBrandGetCurrentValidBrand();
		$brand-config: _oBrandGetConfig($component, $brand);
		$brand-variables: map-get($brand-config, 'variables');
		@if type-of($from) == 'null' {
			// Get from default variables.
			$from: $brand-variables;
		} @else if type-of($from) == 'string' {
			// Get from variant variables.
			$from: map-get($brand-variables, $from);
		}
	}

	// No variable values defined.
	@if type-of($from) != 'map' {
		@return null;
	}

	// Get and concatenate requested variable values.
	$values: null;
	@each $variable in $variables {
		$value: map-get($from, $variable);
		@if type-of($value) == 'map' {
			@return _oBrandError('Could not get variable "#{$variable}" for component "#{component}" as it is a map of variant variables.');
		}
		@if $values {
			$values: join($values, $value);
		} @else {
			$values: $value;
		}
	}

	@return $values;
}

/// Check if the brand supports a variant.
///
/// @example scss
///     oBrandSupportsVariant($component: 'o-component', $variant: 'breadcrumbs');
///     oBrandSupportsVariant($component: 'o-component', $variant: 'inverse');
///
/// @access public
/// @param {string} $component
/// @param {string} $variant
/// @return {boolean}
///
@function oBrandSupportsVariant($component, $variant) {
	// Validate component name.
	$validated-component-name: _oBrandValidateName('Component', $component, 'Cannot check component "#{$component}" supports variant "#{$variant}"');
	// A custom or null variant is always supported.
	@if type-of($variant) == 'map' and type-of($variant) == 'null' {
		@return true;
	}

	// Confirm the variant is valid, to provide a useful error in case of typos etc.
	$validated: _oBrandValidateName(
		'Variant',
		$variant,
		'Cannot check if component "#{$component}" supports variant "#{$variant}"'
	);

	// Check support for a pre-defined variant.
	$brand: _oBrandGetCurrentValidBrand();
	$brand-config: _oBrandGetConfig($component, $brand);
	$supports-variants: map-get($brand-config, 'supports-variants');

	@if type-of($supports-variants) == 'list' {
		@return if(index($supports-variants, $variant), true, false);
	}
	@if type-of($supports-variants) == 'string' {
		@return $variant == $supports-variants;
	}
	// No variants are supported.
	@return false;
}

/// Check if a brand is the one in use.
///
/// @example scss - When the current brand is set to "core"
///     oBrandIs($brand: 'core'); // true
///     oBrandIs($brand: 'internal'); // false
///
/// @access public
/// @throw Errors if an invalid brand has been set by the user.
/// @param {string} $brand
/// @return {boolean}
///
@function oBrandIs($brand) {
	$current-brand: oBrandGetCurrent();

	@if not index($_o-brand-available-brands, $current-brand) {
		@return _oBrandError('The brand "#{$current-brand}" is not supported by o-brand. Please use one of #{$_o-brand-available-brands}.');
	}

	@return $brand == $current-brand;
}

/// Get current brand in use.
/// @access public
///
@function oBrandGetCurrent() {
	@return if($o-brand, $o-brand, $_o-brand-default);
}
