$-zf-flex-justify: (
  'left': flex-start,
  'right': flex-end,
  'center': center,
  'justify': space-between,
  'spaced': space-around,
);

$-zf-flex-align: (
  'top': flex-start,
  'bottom': flex-end,
  'middle': center,
  'stretch': stretch,
);

$-zf-flex-direction: (
  'row': row,
  'row-reverse': row-reverse,
  'column': column,
  'column-reverse': column-reverse,
);

/// Iterates through breakpoints defined in `$breakpoint-classes` and prints the CSS inside the mixin at each breakpoint's media query. Use this with the grid, or any other component that has responsive classes.
///
/// @param {Boolean} $small [true] - If `false`, the mixin will skip the `small` breakpoint. Use this with components that don't prefix classes with `small-`, only `medium-` and up.
@mixin -zf-each-breakpoint($small: true) {
  $list: $breakpoint-classes;

  @if not $small {
    $list: sl-remove($list, $-zf-zero-breakpoint);
  }

  @each $name in $list {
    $-zf-size: $name !global;

    @include breakpoint($name) {
      @content;
    }
  }
}

/// Enables flexbox by adding `display: flex` to the element.
@mixin flex {
  display: flex;
}

/// Horizontally or vertically aligns the items within a flex container.
///
/// @param {Keyword} $x [null] - Horizontal alignment to use. Can be `left`, `right`, `center`, `justify`, or `spaced`. Or, set it to `null` (the default) to not set horizontal alignment.
/// @param {Keyword} $y [null] - Vertical alignment to use. Can be `top`, `bottom`, `middle`, or `stretch`. Or, set it to `null` (the default) to not set vertical alignment.
@mixin flex-align($x: null, $y: null) {
  @if $x {
    @if map-has-key($-zf-flex-justify, $x) {
      $x: map-get($-zf-flex-justify, $x);
    }
    @else {
      @warn 'flex-grid-row-align(): #{$x} is not a valid value for horizontal alignment. Use left, right, center, justify, or spaced.';
    }
  }

  @if $y {
    @if map-has-key($-zf-flex-align, $y) {
      $y: map-get($-zf-flex-align, $y);
    }
    @else {
      @warn 'flex-grid-row-align(): #{$y} is not a valid value for vertical alignment. Use top, bottom, middle, or stretch.';
    }
  }

  justify-content: $x;
  align-items: $y;
}

/// Vertically align a single column within a flex row. Apply this mixin to a flex column.
///
/// @param {Keyword} $y [null] - Vertical alignment to use. Can be `top`, `bottom`, `middle`, or `stretch`. Or, set it to `null` (the default) to not set vertical alignment.
@mixin flex-align-self($y: null) {
  @if $y {
    @if map-has-key($-zf-flex-align, $y) {
      $y: map-get($-zf-flex-align, $y);
    }
    @else {
      @warn 'flex-grid-column-align(): #{$y} is not a valid value for alignment. Use top, bottom, middle, or stretch.';
    }
  }

  align-self: $y;
}

/// Changes the source order of a flex child. Children with lower numbers appear first in the layout.
/// @param {Number} $order [0] - Order number to apply.
@mixin flex-order($order: 0) {
  order: $order;
}

/// Change flex-direction
/// @param {Keyword} $direction [row] - Flex direction to use. Can be
///   - row (default): same as text direction
///   - row-reverse: opposite to text direction
///   - column: same as row but top to bottom
///   - column-reverse: same as row-reverse top to bottom
@mixin flex-direction($direction: row) {
  flex-direction: $direction;
}

@mixin foundation-flex-classes {
  // Horizontal alignment using justify-content
  @each $hdir, $prop in map-remove($-zf-flex-justify, left) {
    .align-#{$hdir} {
      @include flex-align($x: $hdir);
    }
  }

  // Vertical alignment using align-items and align-self
  @each $vdir, $prop in $-zf-flex-align {
    .align-#{$vdir} {
      @include flex-align($y: $vdir);
    }

    .align-self-#{$vdir} {
      @include flex-align-self($y: $vdir);
    }
  }

  // Central alignment of content
  .align-center-middle {
    @include flex-align($x: center, $y: middle);
    align-content: center;
  }

  // Source ordering
  @include -zf-each-breakpoint {
    @for $i from 1 through 6 {
      .#{$-zf-size}-order-#{$i} {
        @include flex-order($i);
      }
    }
  }
}

@include foundation-flex-classes;
@include foundation-flex-grid;