// NGN Chassis
// Typography Mixins -----------------------------------------------------------

// @mixin global-typography-rules
// Generate default typography rules for standard elements
// This mixin is used in the chassis-sass core package to establish typography
// rules at each breakpoint
// @param $upper-bound
// Upper Bound of viewport-width-range to match against
@mixin global-typography-rules($upper-bound) {
  $root-font-size: get-font-size(root, $upper-bound);
  $root-line-height: get-line-height(root, $upper-bound);

  font-size: $root-font-size;
  line-height: $root-line-height;

  h1 {
    font-size: ( ( get-font-size($h1-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h1-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  h2 {
    font-size: ( ( get-font-size($h2-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h2-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  h3 {
    font-size: ( ( get-font-size($h3-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h3-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  h4 {
    font-size: ( ( get-font-size($h4-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h4-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  h5 {
    font-size: ( ( get-font-size($h5-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h5-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  h6 {
    font-size: ( ( get-font-size($h6-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($h6-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  legend {
    font-size: ( ( get-font-size($form-legend-font-size-alias, $upper-bound) / $root-font-size ) * 1em );
    line-height: ( ( get-line-height($form-legend-font-size-alias, $upper-bound) / $root-line-height ) * 1em );
  }

  // Container Elements
  section,
  nav,
  form {
    margin-bottom: ( ( get-line-height(root, $upper-bound) / get-font-size(root, $upper-bound) ) * $type-scale-ratio ) * 1em;
  }

  // Inner Elements
  // section section,
  nav section,
  section nav,
  nav nav,
  article,
  fieldset,
  figure,
  pre,
  blockquote,
  table,
  canvas,
  embed {
    margin-bottom: ( get-line-height(root, $upper-bound) / get-font-size(root, $upper-bound) ) * 1em;
  }

  p {
    margin-bottom: 1em;
  }
}

// @mixin set-typography
// Sets font-size and line-height, and optionally margin-bottom, on an element
// based on Golden Ratio Typography rules, in ems
// @param {string} $alias
// Name of font-size alias (as defined in ./definitions)
// @param {int} $multiplier
// Integer to multiply calculated property values by
// @param {bool} $has-margin
// Determines whether or not to add a calculated bottom-margin property
@mixin set-typography($alias: root, $multiplier: 1, $has-margin: false) {

  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {

    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);
    $upper-bound: map-get($range-bounds, upper-bound);

    $font-size: ( get-font-size($alias, $upper-bound) * $multiplier );
    $line-height: ( get-line-height($alias, $upper-bound) * $multiplier );

    @if $index == 1 {
      @include max-viewport-width($range-semantic-name) {
        font-size: $font-size;
        line-height: $line-height;

        @if $has-margin {
          margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
        }
      }
    } @elseif $index == length($viewport-width-ranges) {
      @include min-viewport-width($range-semantic-name) {
        font-size: $font-size;
        line-height: $line-height;

        @if $has-margin {
          margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
        }
      }
    } @else {
      @include at-viewport-width($range-semantic-name) {
        font-size: $font-size;
        line-height: $line-height;

        @if $has-margin {
          margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
        }
      }
    }

  }
}

@mixin font-size($alias: root, $multiplier: 1) {
  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {

    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);
    $upper-bound: map-get($range-bounds, upper-bound);

    $font-size: ( get-font-size($alias, $upper-bound) * $multiplier );

    @if $index == 1 {
      @include max-viewport-width($range-semantic-name) {
        font-size: $font-size;
      }
    } @elseif $index == length($viewport-width-ranges) {
      @include min-viewport-width($range-semantic-name) {
        font-size: $font-size;
      }
    } @else {
      @include at-viewport-width($range-semantic-name) {
        font-size: $font-size;
      }
    }
  }
}

@mixin line-height($alias: root, $multiplier: 1) {

  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {

    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);
    $upper-bound: map-get($range-bounds, upper-bound);

    $line-height: ( get-line-height($alias, $upper-bound) * $multiplier );

    @if $index == 1 {
      @include max-viewport-width($range-semantic-name) {
        line-height: $line-height;
      }
    } @elseif $index == length($viewport-width-ranges) {
      @include min-viewport-width($range-semantic-name) {
        line-height: $line-height;
      }
    } @else {
      @include at-viewport-width($range-semantic-name) {
        line-height: $line-height;
      }
    }

  }
}

@mixin margin-bottom($alias: root, $multiplier: 1) {

  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {

    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);
    $upper-bound: map-get($range-bounds, upper-bound);

    $line-height: ( get-line-height($alias, $upper-bound) * $multiplier );

    @if $index == 1 {
      @include max-viewport-width($range-semantic-name) {
        margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
      }
    } @elseif $index == length($viewport-width-ranges) {
      @include min-viewport-width($range-semantic-name) {
        margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
      }
    } @else {
      @include at-viewport-width($range-semantic-name) {
        margin-bottom: ( $line-height / get-font-size(root, $upper-bound) ) * 1em;
      }
    }

  }
}

// Typography-based Layout Mixins ----------------------------------------------

// @mixin inline-layout-rules
// Sets margin, padding, and line-height on inline elements that are not just
// plain text, ie buttons, form fields, tags, etc.
// Values are calculated in ems using Golden Ratio Typography rules
// @param {string} $alias
// Default font-size category for this element
// @param {bool} $has-padding
// Determines whether or not to output padding rules
// @param {bool} $has-margin
// Determines whether or not to output margin rules
// @param {bool} $multi-line
// If element displays inline but can contain multiple lines of text within
// itself, like a textarea or contenteditable, set this to true. This will
// ensure correct line-height.
// @param {bool} $add-height-rule
// Add height rule that matches line-height. Useful in browsers which do not
// resize containers in respect to line-height
@mixin inline-layout-rules($alias: root, $has-padding: true, $has-margin: true, $has-margin-bottom: true, $multi-line: false, $add-height-rule: false, $use-base-line-height: false) {
  $font-size-on-previous-iteration: null;

  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {
    // Loop Index
    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);

    // Upper Bound of current Viewport Width Range
    $upper-bound: map-get($range-bounds, upper-bound);

    // Font Size in ems
    $font-size: (get-font-size($alias, $upper-bound) / get-font-size(root, $upper-bound)) * 1em;
    // Default Line Height in ems
    $base-line-height: (get-line-height($alias, $upper-bound) / get-font-size(root, $upper-bound)) * 1em;
    // $base-line-height: (calculate-line-height(get-font-size($alias, $upper-bound), $upper-bound) * 1em );

    // Write rules if returned font-size is different than on previous iteration
    @if $font-size != $font-size-on-previous-iteration {

      // First iteration
      @if $index == 1 {

        // Add calculated margin
        @if $has-margin {
          @if $has-margin-bottom {
            margin: 0 ( $base-line-height / 2 ) $base-line-height 0;
          } @else {
            margin: 0 ( $base-line-height / 2 ) 0 0;
          }
        }

        // Add calculated padding
        @if $has-padding {
          @if $multi-line {
            padding: ( ( ( $base-line-height * $type-scale-ratio ) - $base-line-height ) / 2 ) ( $base-line-height / 2 );
          } @else {
            padding: 0 ( $base-line-height / 2 );
          }
        }

        // For elements that display multiple lines of text
        @if $multi-line {
          line-height: $base-line-height;

          @if $add-height-rule {
            height: $base-line-height;
          }

        // For single-line elements
        } @else {

          @if $use-base-line-height {
            line-height: $base-line-height;
          } @else {
            line-height: ( $base-line-height * $type-scale-ratio );
          }

          @if $add-height-rule {
            @if $use-base-line-height {
              height: $base-line-height;
            } @else {
              height: ( $base-line-height * $type-scale-ratio );
            }
          }
        }

      // All iterations after the first
      } @else {

        @include min-viewport-width($range-semantic-name) {
          @if $has-margin {
            margin: 0 ( $base-line-height / 2 ) $base-line-height 0;
          }

          @if $has-padding {

            @if $multi-line {
              padding: ( ( ( $base-line-height * $type-scale-ratio ) - $base-line-height ) / 2 ) ( $base-line-height / 2 );
            } @else {
              padding: 0 ( $base-line-height / 2 );
            }
          }

          @if $multi-line {
            line-height: $base-line-height;

            @if $add-height-rule {
              height: $base-line-height;
            }
          } @else {
            @if not variable-exists(adjusted-line-height) {
              $adjusted-line-height: ( $base-line-height * $type-scale-ratio );
              line-height: $adjusted-line-height;

              @if $add-height-rule {
                height: $adjusted-line-height;
              }
            }
          }
        }

      }
    }

    $font-size-on-previous-iteration: $font-size;
  }

}

// @mixin block-layout-rules
// Sets margin, padding, and line-height on block elements
// Values are calculated in ems using Golden Ratio Typography rules
// @param {bool} $has-padding
// Determines whether or not to output padding rules
// @param {bool} $has-margin
// Determines whether or not to output margin rules
@mixin block-layout-rules($alias: root, $has-padding: true, $has-margin: true) {
  $font-size-on-previous-iteration: null;

  @each $range-semantic-name, $range-bounds in $viewport-width-ranges {

    $index: index(map-keys($viewport-width-ranges), $range-semantic-name);
    $upper-bound: map-get($range-bounds, upper-bound);

    $font-size: ((get-font-size($alias, $upper-bound) / get-font-size(root, $upper-bound)) * 1em );
    $line-height: (calculate-line-height(get-font-size($alias, $upper-bound), $upper-bound) * 1em );

    @if $font-size != $font-size-on-previous-iteration {
      @if $index == 1 {

        @if $has-margin {
          margin: 0 0 $line-height 0;
        }

        @if $has-padding {
          padding: ( ( $line-height / $type-scale-ratio ) / 2 ) 1em;
        }

      } @else {

        @include min-viewport-width($range-semantic-name) {
          @if not ( variable-exists(margin) ) and $has-margin {
            $margin: 0 0 $line-height 0;
            margin: $margin;
          }

          @if not ( variable-exists(padding) ) and $has-padding {
            $padding: ( ( $line-height / $type-scale-ratio ) / 2 ) 1em;
            padding: $padding;
          }
        }

      }
    }

    $font-size-on-previous-iteration: $font-size;
  }

}
