// stylelint-disable declaration-no-important

@use "sass:map";
@use "sass:math";
@use "sass:string";
@use "../settings" as *;
@use "functions" as *;
@use "sass-mq" as *;

////
/// Typography
///
/// These mixins allow us to quickly and consistently generate common text
/// patterns such as colours and font-weight
///
/// @group tools
////

/// Text colour
///
/// Sets the text colour, including a suitable override for print.
///
/// @link https://github.com/alphagov/govuk-frontend Original code taken from GDS (Government Digital Service)

@mixin nhsuk-text-colour {
  color: $nhsuk-text-colour;

  @include nhsuk-media-query($media-type: print) {
    color: $nhsuk-print-text-colour;
  }
}

/// Text colour (deprecated)
///
/// @alias nhsuk-text-colour
/// @deprecated To be removed in v11.0, replaced by nhsuk-text-colour

@mixin nhsuk-text-color {
  @include nhsuk-warning("color-to-colour", "nhsuk-text-color is deprecated. Use nhsuk-text-colour instead.");
  @include nhsuk-text-colour;
}

/// Normal font weight
///
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`. Generally Used to create override classes.

@mixin nhsuk-font-weight-normal($important: false) {
  @if $important == true {
    font-weight: $nhsuk-font-weight-normal !important;
  } @else {
    font-weight: $nhsuk-font-weight-normal;
  }
}

/// Normal typography weight (deprecated)
///
/// @alias nhsuk-font-weight-normal
/// @deprecated To be removed in v11.0, replaced by nhsuk-font-weight-normal

@mixin nhsuk-typography-weight-normal($important: false) {
  @include nhsuk-warning(
    "nhsuk-typography-weight",
    "nhsuk-typography-weight-normal is deprecated. Use nhsuk-font-weight-normal instead."
  );
  @include nhsuk-font-weight-normal($important);
}

/// Bold font weight
///
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`. Generally Used to create override classes.

@mixin nhsuk-font-weight-bold($important: false) {
  @if $important == true {
    font-weight: $nhsuk-font-weight-bold !important;
  } @else {
    font-weight: $nhsuk-font-weight-bold;
  }
}

/// Bold typography weight (deprecated)
///
/// @alias nhsuk-font-weight-bold
/// @deprecated To be removed in v11.0, replaced by nhsuk-font-weight-bold

@mixin nhsuk-typography-weight-bold($important: false) {
  @include nhsuk-warning(
    "nhsuk-typography-weight",
    "nhsuk-typography-weight-bold is deprecated. Use nhsuk-font-weight-bold instead."
  );
  @include nhsuk-font-weight-bold($important);
}

/// Code font helper
///
/// Used for codes and sequences
///
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`. Generally used to create override classes.

@mixin nhsuk-font-code($important: false) {
  @include nhsuk-font-monospace($important);
  letter-spacing: 0.075em;
  word-spacing: -0.5ch;
}

/// Monospace font helper
///
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`. Generally used to create override classes.

@mixin nhsuk-font-monospace($important: false) {
  $font-family-value: $nhsuk-code-font;

  @if $important == true {
    $font-family-value: $font-family-value !important;
  }

  font-family: $font-family-value;
  font-size-adjust: 0.5;
}

/// Word break helper
///
/// Forcibly breaks long words that lack spaces, such as email addresses,
/// across multiple lines when they wouldn't otherwise fit.
///
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`. Generally used to create override classes.

@mixin nhsuk-text-break-word($important: false) {
  $properties: (
    // IE 11 and Edge 16–17 only support the non-standard `word-wrap` property
    "word-wrap": break-word,

    // All other browsers support `overflow-wrap`
    "overflow-wrap": break-word
  );

  // Workaround to avoid deprecated `if()` function
  @each $property, $value in $properties {
    @if $important == true {
      #{$property}: $value !important;
    } @else {
      #{$property}: $value;
    }
  }
}

/// Line height
///
///
/// Convert line-heights specified in pixels into a relative value, unless
/// they are already unit-less (and thus already treated as relative values),
/// in rems, or the units do not match the units used for the font size.
///
/// @param {Number} $line-height Line height
/// @param {Number} $font-size Font size
/// @return {Number} The line height as either a relative value or unmodified

@function nhsuk-line-height($line-height, $font-size) {
  @if not math.is-unitless($line-height) {
    @if math.compatible($line-height, 1rem) and math.compatible($font-size, 1px) {
      $line-height: math.div($line-height, 1rem) * $nhsuk-root-font-size;

      @if math.is-unitless($font-size) {
        $font-size: $font-size * 1px;
      }
    }

    @if math.compatible($line-height, 1px) and math.compatible($font-size, 1rem) {
      $font-size: math.div($font-size, 1rem) * $nhsuk-root-font-size;
    }

    @if math.unit($line-height) == math.unit($font-size) {
      $line-height: math.div($line-height, $font-size);
    }
  }

  @return $line-height;
}

/// Font size and line height helper
///
/// Takes a point from the responsive 'font map' as an argument (the size as it
/// would appear on tablet and above), and uses it to create font-size and
/// line-height declarations for different breakpoints, and print.
///
/// Example font map:
///
/// ```scss
/// 19: (
///   null: (
///     font-size: 16px,
///     line-height: 20px
///   ),
///   tablet: (
///     font-size: 19px,
///     line-height: 25px
///   ),
///   print: (
///     font-size: 14pt,
///     line-height: 1.15
///   )
/// );
/// ```
///
/// @param {Number | String} $size - Point from the typography scale (the size
///   as it would appear on tablet and above)
/// @param {Number} $line-height [false] - Non responsive custom line
///   height. Omit to use the line height from the font map.
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`.
///
/// @throw if `$size` is not a valid point from the typography scale
///
/// @link https://github.com/alphagov/govuk-frontend Original code taken from GDS (Government Digital Service)

@mixin nhsuk-font-size($size, $line-height: false, $important: false) {
  // Flag font sizes that start with underscores so we can suppress warnings on
  // deprecated sizes used internally, for example `nhsuk-font($size: "_24")`
  $size-internal-use-only: string.slice(#{$size}, 1, 1) == "_";

  // Remove underscore from font sizes flagged for internal use
  @if $size-internal-use-only {
    $size: string.slice(#{$size}, 2);
  }

  // Check for a font map exactly matching the given size
  $font-map: map.get($nhsuk-typography-scale, $size);

  // No match? Try with string type (e.g. $size: "16" not 16)
  @if not $font-map {
    @each $font-size in map.keys($nhsuk-typography-scale) {
      @if not $font-map and "#{$font-size}" == "#{$size}" {
        $font-map: map.get($nhsuk-typography-scale, $font-size);
      }
    }
  }

  // Still no match? Throw error
  @if not $font-map {
    @error "Unknown font size `#{$size}` - expected a point from the typography scale.";
  }

  // Check for a deprecation within the typography scale
  $deprecation: map.get($font-map, "deprecation");

  @if $deprecation {
    // Warn on deprecated font sizes unless flagged for internal use
    @if not $size-internal-use-only {
      @include nhsuk-warning(map.get($deprecation, "key"), map.get($deprecation, "message"));
    }

    // remove the deprecation map keys so they do not break the breakpoint loop
    $font-map: map.remove($font-map, "deprecation");
  }

  @each $breakpoint, $breakpoint-map in $font-map {
    $font-size: map.get($breakpoint-map, "font-size");
    $font-size-rem: nhsuk-px-to-rem($font-size);

    // $calculated-line-height is a separate variable from $line-height,
    // as otherwise the value would get redefined with each loop and
    // eventually break nhsuk-line-height.
    $calculated-line-height: $line-height;
    @if $line-height == false {
      $calculated-line-height: map.get($breakpoint-map, "line-height");
    }

    // We continue to call the param $line-height to stay consistent with the
    // naming with nhsuk-font.
    $calculated-line-height: nhsuk-line-height(
      $line-height: $calculated-line-height,
      $font-size: $font-size
    );

    // Mark rules as !important if $important is true - this will result in
    // these variables becoming strings, so this needs to happen *after* they
    // are used in calculations
    @if $important == true {
      $font-size: $font-size !important;
      $font-size-rem: $font-size-rem !important;
      $calculated-line-height: $calculated-line-height !important;
    }

    & {
      @if not $breakpoint {
        font-size: $font-size-rem;
        line-height: $calculated-line-height;
      } @else if $breakpoint == "print" {
        @include nhsuk-media-query($media-type: print) {
          font-size: $font-size;
          line-height: $calculated-line-height;
        }
      } @else {
        @include nhsuk-media-query($from: $breakpoint) {
          font-size: $font-size-rem;
          line-height: $calculated-line-height;
        }
      }
    }
  }
}

/// Font size and line height helper (deprecated)
///
/// @param {Number | Boolean | String} $size - Point from the typography scale
///   (the size as it would appear on tablet and above). Use `false` to avoid
///   setting a size.
/// @param {Number} $override-line-height [false] - Non responsive custom line
///   height. Omit to use the line height from the font map.
/// @param {Boolean} $important [false] - Whether to mark declarations as
///   `!important`.
///
/// @throw if `$size` is not a valid point from the typography scale (or false)
///
/// @alias nhsuk-font-size
/// @deprecated To be removed in v11.0, replaced by nhsuk-font-size

@mixin nhsuk-typography-responsive($size, $override-line-height: false, $important: false) {
  @include nhsuk-warning(
    "nhsuk-typography-responsive",
    "nhsuk-typography-responsive is deprecated. Use nhsuk-font-size instead."
  );
  @include nhsuk-font-size($size, $override-line-height, $important);
}

/// Font helper
///
/// @example scss
///   .foo {
///     @include nhsuk-font(19);
///   }
///
///   .foo {
///     @include nhsuk-font(36, $weight: bold);
///   }
///
/// @param {Number} $size - Size of the font as it would appear on desktop -
///   uses the responsive font size map
/// @param {String} $weight [normal] - Weight: `bold` or `normal`
/// @param {Number} $line-height [false] - Line-height, if overriding the default

@mixin nhsuk-font($size, $weight: normal, $line-height: false) {
  & {
    @if $weight == normal {
      @include nhsuk-font-weight-normal;
    } @else if $weight == bold {
      @include nhsuk-font-weight-bold;
    }
  }

  @if $size {
    @include nhsuk-font-size($size, $line-height);
  }
}
