@use "./breakpoints.scss";
@use "sass:map";

// Basic font families used throughout
$font-family-sans:
  "din-2014", "Sohne", "Sohne fallback", "Helvetica Neue", Helvetica,
  Arial, sans-serif;
$font-family-serif: Georgia, Times, serif;
$font-family-magazine: "Jubilat", Georgia, Times, serif;
$font-families: (
  "sans": $font-family-sans,
  "serif": $font-family-serif,
  "magazine": $font-family-magazine,
) !default;

@mixin font-family($family: "sans") {
  @if not map.has-key($font-families, $family) {
    @error "Invalid font family `#{$family}`. "
      + "Available familes are #{map.keys($font-families)}";
  } @else {
    font-family: map.get($font-families, $family);
  }
}

// Map of headline/title outlet options onto font families
$headline-outlets: (
  "interactive": "sans",
  "magazine": "magazine",
) !default;

@mixin headline-outlet-font-family($outlet: "interactive") {
  @if not map.has-key($headline-outlets, $outlet) {
    @error "Invalid headline outlet `#{$outlet}`. "
      + "Available outlets are #{map.keys($headline-outlets)}";
  } @else {
    @include font-family($family: map.get($headline-outlets, $outlet));
  }
}

// Font size scale for body/component text
$font-size-text-800: 2rem;
$font-size-text-700: 1.75rem;
$font-size-text-600: 1.5625rem;
$font-size-text-500: 1.375rem;
$font-size-text-400: 1.25rem;
$font-size-text-300: 1.125rem;
$font-size-text-200: 1rem;
$font-size-text-100: 0.875rem;
$font-size-text-000: 0.75rem;
$font-sizes-text: (
  "800": $font-size-text-800,
  "700": $font-size-text-700,
  "600": $font-size-text-600,
  "500": $font-size-text-500,
  "400": $font-size-text-400,
  "300": $font-size-text-300,
  "200": $font-size-text-200,
  "100": $font-size-text-100,
  "000": $font-size-text-000,
) !default;

// Font size scale for headlines
$font-size-headline-700: 4.8125rem;
$font-size-headline-600: 4.25rem;
$font-size-headline-500: 3.75rem;
$font-size-headline-400: 3.3125rem;
$font-size-headline-300: 2.9375rem;
$font-size-headline-200: 2.625rem;
$font-size-headline-100: 2.3125rem;
$font-sizes-headline: (
  "700": $font-size-headline-700,
  "600": $font-size-headline-600,
  "500": $font-size-headline-500,
  "400": $font-size-headline-400,
  "300": $font-size-headline-300,
  "200": $font-size-headline-200,
  "100": $font-size-headline-100,
) !default;

// Font size scale for titles
$font-size-title-700: 2.0625rem;
$font-size-title-600: 1.8125rem;
$font-size-title-500: 1.625rem;
$font-size-title-400: 1.4375rem;
$font-size-title-300: 1.25rem;
$font-size-title-200: 1.125rem;
$font-size-title-100: 1rem;
$font-sizes-title: (
  "700": $font-size-title-700,
  "600": $font-size-title-600,
  "500": $font-size-title-500,
  "400": $font-size-title-400,
  "300": $font-size-title-300,
  "200": $font-size-title-200,
  "100": $font-size-title-100,
) !default;

@function get-font-size($scale, $size) {
  $font-size-scales: (
    "text": $font-sizes-text,
    "headline": $font-sizes-headline,
    "title": $font-sizes-title,
  );

  @if not map.has-key($font-size-scales, $scale) {
    @error "Invalid font size scale `#{$scale}`. "
      + "Available size scales are #{map.keys($font-size-scales)}";
  }

  $size-scale: map.get($font-size-scales, $scale);

  @if not map.has-key($size-scale, $size) {
    @error "Invalid font size `#{$size}` for scale `#{$scale}`. "
      + "Available sizes for scale `#{$scale}` are #{map.keys($size-scale)}";
  }

  @return map.get($size-scale, $size);
}

@mixin font-size-text($size: "300") {
  font-size: get-font-size("text", $size);
}

@mixin font-size-headline($size: "700") {
  font-size: get-font-size("headline", $size);
}

@mixin font-size-title($size: "700") {
  font-size: get-font-size("title", $size);
}

// Font line height multipliers to calculate lh from font size
$font-line-height-multiplier-headline: 1.2;
$font-line-height-multiplier-title: 1.2;
$font-line-height-multiplier-body: 1.615;
$font-line-height-multiplier-component: 1.3;
$font-line-height-multiplier-label: 1;
$font-line-height-multipliers: (
  "body": $font-line-height-multiplier-body,
  "component": $font-line-height-multiplier-component,
  "label": $font-line-height-multiplier-label,
) !default;

@mixin line-height-text($size: "300", $role: "body") {
  @if not map.has-key($font-line-height-multipliers, $role) {
    @error "Invalid font role `#{$role}`. "
      + "Available sizes are #{map.keys($font-line-height-multipliers)}";
  } @else {
    $font-size: get-font-size("text", $size);
    $height-multiplier: map.get($font-line-height-multipliers, $role);

    line-height: $font-size * $height-multiplier;
  }
}

@mixin line-height-headline($size: "700") {
  $font-size: get-font-size("headline", $size);

  line-height: $font-size * $font-line-height-multiplier-headline;
}

@mixin line-height-title($size: "700") {
  $font-size: get-font-size("title", $size);

  line-height: $font-size * $font-line-height-multiplier-title;
}

// Font weights
$font-weight-light: lighter;
$font-weight-regular: normal;
$font-weight-bold: bold;
$font-weights: (
  "light": $font-weight-light,
  "regular": $font-weight-regular,
  "bold": $font-weight-bold,
) !default;

@mixin font-weight($weight: "regular") {
  @if not map.has-key($font-weights, $weight) {
    @error "Invalid font weight `#{$weight}`. "
      + "Available weights are #{map.keys($font-weights)}";
  } @else {
    font-weight: map.get($font-weights, $weight);
  }
}

// Letter spacing
$letter-spacing-text: (
  "000": 1.6px,
  "100": 0.2px,
  "200": 0,
  "300": 0,
  "400": 0,
  "500": 0,
  "600": 0,
  "700": 0,
  "800": 0,
);
$letter-spacing-headline: (
  "100": -0.35px,
  "200": -0.45px,
  "300": -0.58px,
  "400": -0.75px,
  "500": -0.98px,
  "600": -1.28px,
  "700": -1.67px,
);
$letter-spacing-title: (
  "100": -0.05px,
  "200": -0.07px,
  "300": -0.09px,
  "400": -0.12px,
  "500": -0.16px,
  "600": -0.21px,
  "700": -0.27px,
);

@mixin letter-spacing($type, $size) {
  $letter-spacings: (
    "text": $letter-spacing-text,
    "headline": $letter-spacing-headline,
    "title": $letter-spacing-title,
  );

  @if not map.has-key($letter-spacings, $type) {
    @error "Invalid letter spacing type `#{$type}`. "
      + "Available types are `#{map.keys($letter-spacings)}`";
  }

  $spacings: map.get($letter-spacings, $type);

  @if not map.has-key($spacings, $size) {
    @error "Invalid font size `#{$size}` for letter spacing type `#{$type}`. "
      + "Available sizes for type `#{$type}` are `#{map.keys($spacings)}`";
  }

  letter-spacing: map.get($spacings, $size);
}

// Mixin for applying basic body/component text styles
@mixin text(
  $family: "serif",
  $size: "300",
  $role: "body",
  $weight: "regular",
  $overline: false
) {
  @include breakpoints.responsive-values($size) using($args) {
    $responsive-size: map.get($args, "value");

    @if $overline {
      @include letter-spacing("text", "000");
    } @else {
      @include letter-spacing("text", $responsive-size);
    }

    @include font-size-text($size: $responsive-size);
    @include line-height-text($size: $responsive-size, $role: $role);
  }

  @include font-family($family: $family);
  @include font-weight($weight: $weight);

  @content;
}

// Convenience mixin for applying sans body/component text styles
@mixin sans($size: "300", $role: "body", $weight: "regular") {
  @include text(
    $family: "sans",
    $size: $size,
    $role: $role,
    $weight: $weight
  ) {
    @content;
  }
}

// Convenience mixin for applying serif body/component text styles
@mixin serif($size: "300", $role: "body", $weight: "regular") {
  @include text(
    $family: "serif",
    $size: $size,
    $role: $role,
    $weight: $weight
  ) {
    @content;
  }
}

// Convenience mixin for applying magazine body/component text styles
@mixin magazine($size: "300", $role: "body", $weight: "regular") {
  @include text(
    $family: "magazine",
    $size: $size,
    $role: $role,
    $weight: $weight
  ) {
    @content;
  }
}

// Convenience mixin for applying overline text styles
@mixin overline($size: "100") {
  text-transform: uppercase;

  @include text(
    $family: "sans",
    $size: $size,
    $role: "component",
    $weight: "bold",
    $overline: true
  ) {
    @content;
  }
}

// Mixin for applying headline styles
@mixin headline(
  $size: (
    "xs": "100",
    "md": "500",
  ),
  $weight: "bold",
  $outlet: "interactive"
) {
  @include breakpoints.responsive-values($size) using($args) {
    $responsive-size: map.get($args, "value");

    @include font-size-headline($size: $responsive-size);
    @include line-height-headline($responsive-size);
    @include letter-spacing("headline", $responsive-size);
  }

  @include headline-outlet-font-family($outlet: $outlet);
  @include font-weight($weight: $weight);

  @content;
}

// Mixin for applying title styles
@mixin title($size: "700", $weight: "bold", $outlet: "interactive") {
  @include breakpoints.responsive-values($size) using($args) {
    $responsive-size: map.get($args, "value");

    @include font-size-title($size: $responsive-size);
    @include line-height-title($responsive-size);
    @include letter-spacing("title", $responsive-size);
  }

  @include headline-outlet-font-family($outlet: $outlet);
  @include font-weight($weight: $weight);

  @content;
}
