//
// @param {string} $breakpoint
// @param {string} $type
// @param {string} $dimension
//
@mixin viewport($breakpoint: 'md', $type: 'max', $dimension: 'width') {
  @if $media-queries {
    $property: null;
    $value: null;
    @if $type != '' {
      $property: #{$type}-#{$dimension + ': ' };
    }
    @else {
      $property: #{$dimension + ': ' };
    }
    @if map-has-key($media-breakpoints, #{$breakpoint}) {
      $value: map-get($media-breakpoints, #{$breakpoint});
    }
    @else {
      $value: $breakpoint;
    }
    $query: $property + if(str-index('' + $value, 'px'), ($value - 0.02), $value);
    @media only screen and (#{$query}) {
      @content;
    }
  }
}

//
// @param {map} $options
// @param {string} $infix
//
@mixin make-options($options, $infix: '') {
  @if is-type('map', $options) {
    @each $property-alias, $property-map in $options {
      $property: map-get($property-map, 'property');
      $wrapper: map-get($property-map, 'wrapper');
      @each $value-alias, $value in map-get($property-map, 'values') {
        .#{$property-alias + $infix}\:#{$value-alias} {
          @if $wrapper != null {
            #{$property}: #{str-replace($wrapper, '%var%', #{$value})};
          }
          @else {
            #{$property}: #{$value};
          }
        }
      }
    }
  }
}

//
// @param {map} $flex-grid
//
@mixin make-flex-grid-pack($flex-grid) {
  $pack-name: map-get(map-get($flex-grid, 'pack'), 'name');
  $breakpoints: map-get(map-get($flex-grid, 'pack'), 'map');
  $containers: map-get(map-get($flex-grid, 'tier'), 'map');
  $gutter-name: map-get(map-get($flex-grid, 'gutter'), 'name');
  $gutter-size: map-get(map-get($flex-grid, 'gutter'), 'size');
  $gutter-axis: map-get(map-get($flex-grid, 'gutter'), 'axis');
  $responsive: map-get(map-get($flex-grid, 'pack'), 'responsive');
  $options: map-get(map-get($flex-grid, 'pack'), 'options');

  %pack {
    @if is-type('number', $gutter-size) {
      @extend %pack-base;
      @if $gutter-axis == 'x' or $gutter-axis == 'y' {
        padding-#{if($gutter-axis == 'x', 'left', 'top')}: $gutter-size;
        padding-#{if($gutter-axis == 'x', 'right', 'bottom')}: $gutter-size;
      }
      @else {
        padding: $gutter-size;
      }
    }
    @else {
      @extend %pack-base;
    }
  }

  .#{$pack-name} {
    @extend %pack;
    @if is-type('map', $breakpoints) {
      @each $breakpoint-key, $value in $breakpoints {
        @include viewport($value, 'min') {
          max-width: map-get($containers, $breakpoint-key);
        }
      }
    }
  }

  .#{$pack-name}\:no-#{$gutter-name} {
    @extend .#{$pack-name};
    @if $gutter-axis == 'x' or $gutter-axis == 'y' {
      padding-#{if($gutter-axis == 'x', 'left', 'top')}: 0;
      padding-#{if($gutter-axis == 'x', 'right', 'bottom')}: 0;
    }
    @else {
      padding: 0;
    }
  }

  @if $options {
    @include make-options($options);
  }

  @if $responsive {
    @if is-type('map', $breakpoints) {
      @each $breakpoint-key, $breakpoint-value in $breakpoints {
        @include viewport($breakpoint-value, 'min') {
          @if $options {
            @include make-options($options, '-' + $breakpoint-key);
          }
        }
      }
    }
  }
}

//
// @param {map} $flex-grid
//
@mixin make-flex-grid-tier($flex-grid) {
  $tier-name: map-get(map-get($flex-grid, 'tier'), 'name');
  $breakpoints: map-get(map-get($flex-grid, 'pack'), 'map');
  $cell-name: map-get(map-get($flex-grid, 'cell'), 'name');
  $gutter-name: map-get(map-get($flex-grid, 'gutter'), 'name');
  $gutter-size: map-get(map-get($flex-grid, 'gutter'), 'size');
  $gutter-axis: map-get(map-get($flex-grid, 'gutter'), 'axis');
  $responsive: map-get(map-get($flex-grid, 'tier'), 'responsive');
  $options: map-get(map-get($flex-grid, 'tier'), 'options');

  %tier {
    @if is-type('number', $gutter-size) {
      @extend %tier-base;
      @if $gutter-axis == 'x' or $gutter-axis == 'y' {
        margin-#{if($gutter-axis == 'x', 'left', 'top')}: $gutter-size * -1;
        margin-#{if($gutter-axis == 'x', 'right', 'bottom')}: $gutter-size * -1;
      }
      @else {
        margin: $gutter-size;
      }
    }
    @else {
      @extend %tier-base;
    }
  }

  .#{$tier-name} {
    @extend %tier;
  }

  .#{$tier-name}\:no-#{$gutter-name} {
    @extend .#{$tier-name};
    @if $gutter-axis == 'x' or $gutter-axis == 'y' {
      margin-#{if($gutter-axis == 'x', 'left', 'top')}: 0;
      margin-#{if($gutter-axis == 'x', 'right', 'bottom')}: 0;
    }
    @else {
      margin: 0;
    }
    > [class*="#{$cell-name}"] {
      @if $gutter-axis == 'x' or $gutter-axis == 'y' {
        padding-#{if($gutter-axis == 'x', 'left', 'top')}: 0;
        padding-#{if($gutter-axis == 'x', 'right', 'bottom')}: 0;
      }
      @else {
        padding: 0;
      }
    }
    .sub-#{$cell-name} {
      margin-#{if($gutter-axis == 'y', 'right', 'bottom')}: 0;
    }
  }

  @if $options {
    @include make-options($options);
  }

  @if $responsive {
    @if is-type('map', $breakpoints) {
      @each $breakpoint-key, $breakpoint-value in $breakpoints {
        @include viewport($breakpoint-value, 'min') {
          @if $options {
            @include make-options($options, '-' + $breakpoint-key);
          }
        }
      }
    }
  }
}

//
// @param {map} $flex-grid
//
@mixin make-flex-grid-cell($flex-grid) {
  $cell-name: map-get(map-get($flex-grid, 'cell'), 'name');
  $breakpoints: map-get(map-get($flex-grid, 'pack'), 'map');
  $members: map-get(map-get($flex-grid, 'cell'), 'map');
  $gutter-size: map-get(map-get($flex-grid, 'gutter'), 'size');
  $gutter-axis: map-get(map-get($flex-grid, 'gutter'), 'axis');
  $responsive: map-get(map-get($flex-grid, 'cell'), 'responsive');
  $options: map-get(map-get($flex-grid, 'cell'), 'options');

  %cell {
    @if is-type('number', $gutter-size) {
      @extend %cell-base;
      @if $gutter-axis == 'x' or $gutter-axis == 'y' {
        padding-#{if($gutter-axis == 'x', 'left', 'top')}: $gutter-size;
        padding-#{if($gutter-axis == 'x', 'right', 'bottom')}: $gutter-size;
      }
      @else {
        padding: $gutter-size;
      }
    }
    @else {
      @extend %cell-base;
    }
  }
  
  .#{$cell-name}\:auto, .#{$cell-name} {
    @extend %cell;
  }

  .#{$cell-name}\:auto {
    flex: 0 0 auto;
  }

  .#{$cell-name} {
    flex: 1 1 auto;
  }

  @if is-type('map', $members) {
    @each $member-key, $member-value in $members {
      .#{$cell-name}\:#{$member-key} {
        @extend %cell;
        flex: 0 0 percentage($member-value);
        max-width: percentage($member-value);
      }
    }
  }

  @if $options {
    @include make-options($options);
  }

  @if $responsive {
    @if is-type('map', $breakpoints) {
      @each $breakpoint-key, $breakpoint-value in $breakpoints {
        $cells-extensions: (); // @extend can't be used inside @media
        @include viewport($breakpoint-value, 'min') {
          $auto-cell: #{$cell-name}-#{$breakpoint-key}\:auto;
          $cells-extensions: append($cells-extensions, $auto-cell);
          .#{$auto-cell} {
            flex: 0 0 auto;
          }
          @each $member-key, $member-value in $members {
            $member-cell: #{$cell-name}-#{$breakpoint-key}\:#{$member-key};
            $cells-extensions: append($cells-extensions, $member-cell);
            .#{$member-cell} {
              flex: 0 0 percentage($member-value);
              max-width: percentage($member-value);
            }
            @if is-fraction($member-value * 100) {
              $floor-cell: #{$cell-name}-#{$breakpoint-key}\:floor;
              $cells-extensions: append($cells-extensions, $floor-cell);
              .#{$floor-cell} {
                &.#{$member-cell} {
                  flex: 0 0 floor(percentage($member-value));
                  max-width: floor(percentage($member-value));
                }
              }
              $ceil-cell: #{$cell-name}-#{$breakpoint-key}\:ceil;
              $cells-extensions: append($cells-extensions, $ceil-cell);
              .#{$ceil-cell} {
                &.#{$member-cell} {
                  flex: 0 0 ceil(percentage($member-value));
                  max-width: ceil(percentage($member-value));
                }
              }
            }
          }
          @if $options {
            @include make-options($options, '-' + $breakpoint-key);
          }
        }
        @each $cell-extension in $cells-extensions {
          .#{$cell-extension} {
            @extend %cell;
          }
        }
      }
    }
  }

  .sub-#{$cell-name} {
    width: 100%;
    height: auto;
    padding: 0;
    margin: 0;
    @if is-type('number', $gutter-size) {
      &:not(:only-child) {
        margin-#{if($gutter-axis == 'y', 'right', 'bottom')}: $gutter-size * 2;
      }
      &:last-child {
        margin-bottom: 0;
      }
    }
  }
}

//
// @param {string} $property
// @param {string} $value
// @param {list} $prefixes
//
@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

//
// @param {string} $property
// @param {string} $value
//
@mixin vendorize($property, $value) {
  @include prefix($property, $value, ('webkit', 'moz', 'ms', 'o'));
}