@use '../config';
@use '../conversion' as convert;
@use 'sass:list';
@use 'sass:map';
@use 'sass:math';
@use 'sass-mq' as mq;

/// Allows usage of global typographic presets instead of definitions spread
/// accross your project. Supports responsive presets (checkout configuration
/// property `$fluid-type` in the example below).
/// @param {enum} $size ['m'] -
///   The key for the requested font size
/// @param {bool} $set-line-height [true] -
///   Set false to exclude 'line-height'
/// @param {bool} $set-vertical-offset [false] -
///   Set true to include 'margin-top' and 'margin-bottom'
/// @output
/// @example scss
///   // Configuration
///   @use '@pixelherz/sassbox' with (
///     $breakpoints: (
///       rat: 768px,
///     ),
///     $font-sizes: (
///       s: 16px,
///       m: 24px,
///       l: 36px,
///     ),
///     $line-heights: (
///       s: 20px,
///       m: 30px,
///       l: 45px,
///     ),
///     $letter-spacing: (
///       s: 0.01em,
///       m: 0.005em,
///       l: 0,
///     ),
///     $vertical-spacing: (
///       s: 20px,
///       m: 30px,
///       l: 45px,
///     ),
///     $fluid-type: (
///       l: (
///         default: 'm',
///         rat: 'l',
///       ),
///       m: (
///         default: 's',
///         rat: 'm',
///       ),
///     ),
///   );
///
///   // Usage
///   .title {
///     @include sassbox.use-type('l');
///   }
///   .paragraph {
///     @include sassbox.use-type('m', $set-vertical-offset: true);
///   }
/// @since 1.0.0
/// @group type

@mixin use-type(
  $size: 'm',
  $set-line-height: true,
  $set-vertical-offset: false,
  $set-responsive: true
) {
  @if ($set-responsive != true) {
    @include -apply-styles($size, $set-line-height, $set-vertical-offset);
  } @else if map.has-key(config.$fluid-type, $size) {
    $bps: map.get(config.$fluid-type, $size);
    @each $bp in $bps {
      $bp-name: list.nth($bp, 1);
      $bp-size: list.nth($bp, 2);
      // Default (no breakpoint)
      @if ($bp-name == 'default') {
        @include -apply-styles(
          $bp-size,
          $set-line-height,
          $set-vertical-offset
        );
      }
      // Breakpoint
      @else if map.has-key(mq.$breakpoints, $bp-name) {
        @include mq.mq($from: $bp-name) {
          @include -apply-styles(
            $bp-size,
            $set-line-height,
            $set-vertical-offset
          );
        }
      }
      // Breakpoint invalid
      @else {
        @warn "Breakpoint '#{$bp-name}' is not defined in $breakpoints. Check your configuration in $fluid-type, make sure $breakpoints is available or add the breakpoint to $breakpoints.";
      }
    }
  } @else {
    @include -apply-styles($size, $set-line-height, $set-vertical-offset);
  }
}

// Helper for mixin use-preset
@mixin -apply-styles(
  $size: 'm',
  $set-line-height: true,
  $set-vertical-offset: false
) {
  // Collect values
  $font-size: map.get(config.$font-sizes, $size);
  $line-height: map.get(config.$line-heights, $size);

  // Output
  font-size: convert.px-to-rem($font-size);
  @if map.has-key(config.$letter-spacing, $size) {
    letter-spacing: map.get(config.$letter-spacing, $size);
  }
  @if $set-line-height {
    line-height: convert.px-to-rem($line-height);
  }
  @if $set-vertical-offset {
    $offset-v-abs: $line-height;
    @if map.has-key(config.$vertical-spacing, $size) {
      $offset-v-abs: map.get(config.$vertical-spacing, $size);
    }
    $offset-v: math.div($offset-v-abs, $font-size) * 1em;
    margin-top: $offset-v;
    margin-bottom: $offset-v;
  }
}

// Legacy support for <1.0.0, can be dropped with >=2.0.0

@mixin font-size(
  $size: 'm',
  $set-line-height: true,
  $set-vertical-offset: false,
  $set-responsive: true
) {
  @warn "Mixin font-size() is deprecated and will be removed. Use use-type() instead.";
  @include use-type(
    $size,
    $set-line-height,
    $set-vertical-offset,
    $set-responsive
  );
}
