.justify-mixin(start) { justify-content: flex-start }
.justify-mixin(end) { justify-content: flex-end }
.justify-mixin(center) { justify-content: center }
.justify-mixin(around) { justify-content: space-around }
.justify-mixin(between) { justify-content: between }
.justify-mixin(@_) {}

.items-mixin(top) { align-items: flex-start; }
.items-mixin(bottom) { align-items: flex-end; }
.items-mixin(center) { align-items: center; }
.items-mixin(stretch) { align-items: stretch; }
.items-mixin(baseline) { align-items: baseline; }
.items-mixin(@_) {}

.item-mixin(top) { align-self: flex-start; }
.item-mixin(bottom) { align-self: flex-end; }
.item-mixin(center) { align-self: center; }
.item-mixin(stretch) { align-self: stretch; }
.item-mixin(baseline) { align-self: baseline; }
.item-mixin(@_) {}

.content-mixin(top) { align-content: flex-start; }
.content-mixin(bottom) { align-content: flex-end; }
.content-mixin(center) { align-content: center; }
.content-mixin(stretch) { align-content: stretch; }
.content-mixin(baseline) { align-content: baseline; }
.content-mixin(@_) {}

.grid(@direction: row; @items: none; @justify: none; @content: none; @wrap: wrap) {
  display: flex;
  flex-wrap: @wrap;
  flex-direction: @direction;

  .justify-mixin(@justify);
  .items-mixin(@item);
  .content-mixin(@content);
}

.row(@items: none; @justify: none; @content: none) {
  .grid(@direction: row, @items, @justify, @content);
}

.column(@items: none; @justify: none; @content: none) {
  .grid(@direction: column; @items; @justify; @content);
}

.margin-mixin(@g) when not (@g = 0) {
  margin: @g / 2;
}

.cell(@i: 1; @item; @g: @grid-gutter-width; @cols: @grid-columns) {
  flex-basis: %('calc(100% * %s - %s)', @i / @cols, @g);
  min-width: 0; // FF adjustment for responsive images
  .item-mixin(@item);
  .margin-mixin(@g);
}

.cell-offset(@i: 1; @g: @grid-gutter-width; @cols: @grid-columns) {
  margin-left: e%('calc(100% * %s + %s)', @i / @cols, @g / 2) !important;
}

.padding-mixin(@pad) when (@pad) {
  padding-left: @pad;
  padding-right: @pad;
}

// center an element
.center(@value: 50%; @padding: 0) {
  margin-left: auto;
  margin-right: auto;
  max-width: @value;
  width: 100%;

  .padding-mixin(@padding);
}

// usage:
// .some-class {
//   .between(sm, xl, {
//     height: 9001px;
//   });
// }
// outputs:
// .some-class {
//   @media only screen and (min-width: @screen-sm) and (max-width: @screen-xl) {
//     height: 9001px;
//   }
// }
//
// where screen-md, screen-xl are bootstrap vars
// min/max can be any of: sm, md, lg, xl
.between(@min; @max; @rules) {
  // BS logic to do string building with conditions
  .condition-wrapper(@new) {
    .redefine-condition() {
      @condition: @new;
    }
  }
  .init-condition() {
    .condition-wrapper('only screen');
  }
  .init-condition();
  .add-min-media(@min) when (iskeyword(@min)) {
    .redefine-condition();
    .condition-wrapper(%('%s and (min-width: @{screen-%s})', @condition, @min));
  }

  .add-max-media(@max) when (iskeyword(@max)) {
    .redefine-condition();
    .condition-wrapper(%('%s and (max-width: @{screen-%s})', @condition, @max));
  }
  .add-min-media(@min);
  .add-max-media(@max);

  .add-query() {
    .redefine-condition();
    @query: e(@condition);
    @media @query {
      @rules();
    }
  }

  .add-query();
}

// usage
// .below(md, {
//   height: 9001px;
//  });
// outputs:
// .some-class {
//   @media only screen and (max-width: @screen-xl) {
//     height: 9001px;
//   }
// }
.below(@max, @rules) {
  .between(@empty; @max; @rules);
}

// usage
// .above(sm, {
//   height: 9001px;
// });
// outputs:
// .some-class {
//   @media only screen and (min-width: @screen-sm) {
//     height: 9001px;
//   }
// }
.above(@min, @rules) {
  .between(@min; @empty; @rules);
}
