//
// Mixins for the Zen Grids system.
//


// Specify the number of columns in the grid. @see http://zengrids.com/help/#zen-column-count
$zen-column-count                 : 1           !default;

// Specify the width of the gutters (as padding). @see http://zengrids.com/help/#zen-gutter-width
$zen-gutter-width                 : 20px        !default;

// @see http://zengrids.com/help/#zen-auto-include-item-base
$zen-auto-include-item-base       : true        !default;
$zen-auto-include-flow-item-base  : true        !default;

// Specify the width of the entire grid. @see http://zengrids.com/help/#zen-grid-width
$zen-grid-width                   : 100%        !default;

// The box-sizing polyfill for IE6/7 requires an absolute path. @see http://zengrids.com/help/#box-sizing-polyfill-path
$box-sizing-polyfill-path         : ""          !default;

// Specify the CSS3 box-sizing method. @see http://zengrids.com/help/#zen-box-sizing
$zen-box-sizing                   : border-box  !default;

// @see http://zengrids.com/help/#legacy-support-for-ie7
$legacy-support-for-ie7           : false       !default;
$legacy-support-for-ie6           : false       !default;

// Specify the default floating direction for zen's mixins. @see http://zengrids.com/help/#zen-float-direction
$zen-float-direction              : left        !default;

// Reverse the floating direction in all zen's mixins. @see http://zengrids.com/help/#zen-reverse-all-floats
$zen-reverse-all-floats           : false       !default;


//
// Apply this to the grid container element.
// @see http://zengrids.com/help/#zen-grid-container
//
@mixin zen-grid-container {
  @if ($legacy-support-for-ie6 or $legacy-support-for-ie7) {
    *position: relative; // @TODO: This is a pre-IE8 line of code; don't remember why its needed.
  }
  // We use the "micro clearfix", instead of Compass' clearfix or pie-clearfix.
  &:before,
  &:after {
    content: "";
    display: table;
  }
  &:after {
    clear: both;
  }
  @if ($legacy-support-for-ie6 or $legacy-support-for-ie7) {
    *zoom: 1;
  }
}

//
// Apply this to any grid item that is also a grid container element for a
// nested grid. @see http://zengrids.com/help/#zen-nested-container
//
@mixin zen-nested-container {
  padding: {
    left: 0;
    right: 0;
  }
}

//
// Apply this to each grid item. @see http://zengrids.com/help/#zen-grid-item
//
@mixin zen-grid-item(
  $column-span,
  $column-position,
  $float-direction          : $zen-float-direction,
  $column-count             : $zen-column-count,
  $gutter-width             : $zen-gutter-width,
  $grid-width               : $zen-grid-width,
  $box-sizing               : $zen-box-sizing,
  $reverse-all-floats       : $zen-reverse-all-floats,
  $auto-include-item-base   : $zen-auto-include-item-base
) {

  // Calculate the unit width.
  $unit-width: zen-unit-width($column-count, $grid-width);

  // Calculate the item's width.
  $width: zen-grid-item-width($column-span, $column-count, $gutter-width, $grid-width, $box-sizing);

  // Determine the float direction and its reverse.
  $dir: $float-direction;
  @if $reverse-all-floats {
    $dir: zen-direction-flip($dir);
  }
  $rev: zen-direction-flip($dir);

  float: $dir;
  width: $width;
  margin: {
    #{$dir}: ($column-position - 1) * $unit-width;
    #{$rev}: (1 - $column-position - $column-span) * $unit-width;
  }

  // Auto-apply the unit base mixin.
  @if $auto-include-item-base {
    @include zen-grid-item-base($gutter-width, $box-sizing);
  }
}

//
// Applies a standard set of properites to all grid items in the layout.
// @see http://zengrids.com/help/#zen-grid-item-base
//
@mixin zen-grid-item-base(
  $gutter-width       : $zen-gutter-width,
  $box-sizing         : $zen-box-sizing,
  $flow-direction     : $zen-float-direction,
  $reverse-all-flows  : $zen-reverse-all-floats
) {

  $dir: $flow-direction;
  @if $reverse-all-flows {
    $dir: zen-direction-flip($dir);
  }

  padding: {
    left: zen-half-gutter($gutter-width, left, $dir);
    right: zen-half-gutter($gutter-width, right, $dir);
  }
  // Specify the border-box properties.
  @if $box-sizing == border-box {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -ms-box-sizing: border-box;
    box-sizing: border-box;
  }
  // Prevent left/right borders since they'll break the layout with content-box.
  @if $box-sizing == content-box {
    border: {
      left: 0 !important;
      right: 0 !important;
    }
  }
  // Prevent overflowing content from being hidden beneath other grid items.
  word-wrap: break-word; // A very nice CSS3 property.

  @if ($legacy-support-for-ie6 or $legacy-support-for-ie7) {
    @if $box-sizing == border-box and $box-sizing-polyfill-path == "" {
      @warn "IE legacy support is on, but $box-sizing is set to #{$box-sizing} and the $box-sizing-polyfill-path is empty.";
    }
    @if $box-sizing-polyfill-path != "" {
      *behavior: url($box-sizing-polyfill-path);
    }
    @if $legacy-support-for-ie6 {
      _display: inline; // Display inline or double your floated margin! [1]
      _overflow: hidden; // Prevent overflowing content from breaking the layout.
      _overflow-y: visible; // In IE6, overflow visible is broken [2]
      // 1. http://www.positioniseverything.net/explorer/doubled-margin.html
      // 2. http://www.howtocreate.co.uk/wrongWithIE/?chapter=overflow%3Avisible%3B
    }
  }
}

//
// Apply this to grid items that need to be cleared below other grid items.
// @see http://zengrids.com/help/#zen-clear
//
@mixin zen-clear(
  $float-direction      : $zen-float-direction,
  $reverse-all-floats   : $zen-reverse-all-floats
) {
  // Determine the float direction.
  $dir: $float-direction;
  @if $reverse-all-floats {
    $dir: zen-direction-flip($dir);
  }
  clear: $dir;
}

//
// Apply this to flow items that need to be floated.
// @see http://zengrids.com/help/#zen-float
//
@mixin zen-float(
  $float-direction      : $zen-float-direction,
  $reverse-all-floats   : $zen-reverse-all-floats
) {
  // Determine the float direction.
  $dir: $float-direction;
  @if $reverse-all-floats {
    $dir: zen-direction-flip($dir);
  }
  float: $dir;
}

//
// Apply this to an HTML item that is in the normal flow of a document to help
// align it to the grid. @see http://zengrids.com/help/#zen-float
//
@mixin zen-grid-flow-item(
  $column-span,
  $parent-column-count          : false,
  $alpha-gutter                 : false,
  $omega-gutter                 : true,
  $flow-direction               : $zen-float-direction,
  $column-count                 : $zen-column-count,
  $gutter-width                 : $zen-gutter-width,
  $grid-width                   : $zen-grid-width,
  $box-sizing                   : $zen-box-sizing,
  $reverse-all-flows            : $zen-reverse-all-floats,
  $auto-include-flow-item-base  : $zen-auto-include-flow-item-base
) {

  $columns: $column-count;
  @if unit($grid-width) == "%" {
    @if $parent-column-count == false {
      @warn "For responsive layouts with a percentage-based grid width, you must set the $parent-column-count to the number of columns that the parent element spans.";
    }
    @else {
      $columns: $parent-column-count;
    }
  }

  $dir: $flow-direction;
  @if $reverse-all-flows {
    $dir: zen-direction-flip($dir);
  }
  $rev: zen-direction-flip($dir);

  // Auto-apply the unit base mixin.
  @if $auto-include-flow-item-base {
    @include zen-grid-item-base($gutter-width, $box-sizing);
  }

  // Calculate the item's width.
  $width: zen-grid-item-width($column-span, $columns, $gutter-width, $grid-width, $box-sizing);

  @if unit($grid-width) == "%" {
    // Our percentage $width is off if the parent has $gutter-width padding.
    // Calculate an adjusted gutter to fix the width.
    $adjusted-gutter: ($columns - $column-span) * $gutter-width / $columns;

    width: $width;

    // Ensure the HTML item either has a full gutter or no gutter on each side.
    padding-#{$dir}: 0;
    @if $alpha-gutter {
      margin-#{$dir}: $gutter-width;
    }
    padding-#{$rev}: $adjusted-gutter;
    @if $omega-gutter {
      margin-#{$rev}: $gutter-width - $adjusted-gutter;
    }
    @else {
      margin-#{$rev}: -($adjusted-gutter);
    }
  }
  @else {
    @if $alpha-gutter and $omega-gutter {
      width: $width;
      @if $gutter-width != 0 {
        margin: {
          #{$dir}: zen-half-gutter($gutter-width, left, $dir);
          #{$rev}: zen-half-gutter($gutter-width, right, $dir);
        }
      }
    }
    @else if not $alpha-gutter and not $omega-gutter {
      width: if($box-sizing == border-box, ($width - $gutter-width), $width);
      @if $gutter-width != 0 {
        padding: {
          left: 0;
          right: 0;
        }
      }
    }
    @else {
      width: $width;
      @if $omega-gutter {
        padding-#{$dir}: 0;
        padding-#{$rev}: $gutter-width;
      }
      @else {
        padding-#{$dir}: $gutter-width;
        padding-#{$rev}: 0;
      }
    }
  }
}


//
// Helper functions for the Zen mixins.
//

// Returns a half gutter width. @see http://zengrids.com/help/#zen-half-gutter
@function zen-half-gutter(
  $gutter-width     : $zen-gutter-width,
  $gutter-side      : $zen-float-direction,
  $flow-direction   : $zen-float-direction
) {
  $half-gutter: $gutter-width / 2;
  // Special handling in case gutter has an odd number of pixels.
  @if unit($gutter-width) == "px" {
    @if $gutter-side == $flow-direction {
      @return floor($half-gutter);
    }
    @else {
      @return ceil($half-gutter);
    }
  }
  @return $half-gutter;
}

// Calculates the unit width of a column. @see http://zengrids.com/help/#zen-unit-width
@function zen-unit-width(
  $column-count   : $zen-column-count,
  $grid-width     : $zen-grid-width
) {
  $unit-width: $grid-width / $column-count;
  @if unit($unit-width) == "px" and floor($unit-width) != ceil($unit-width) {
    @warn "You may experience rounding errors as the grid width, #{$grid-width}, does not divide evenly into #{$column-count} columns.";
  }
  @return $unit-width;
}

// Calculates the width of a grid item that spans the specified number of columns.
// @see http://zengrids.com/help/#zen-grid-item-width
@function zen-grid-item-width(
  $column-span,
  $column-count   : $zen-column-count,
  $gutter-width   : $zen-gutter-width,
  $grid-width     : $zen-grid-width,
  $box-sizing     : $zen-box-sizing
) {
  $width: $column-span * zen-unit-width($column-count, $grid-width);
  @if $box-sizing == content-box {
    @if not comparable($width, $gutter-width) {
      $units-gutter: unit($gutter-width);
      $units-grid: unit($grid-width);
      @warn "The layout cannot be calculated correctly; when using box-sizing: content-box, the units of the gutter (#{$units-gutter} did not match the units of the grid width (#{$units-grid}).";
    }
    $width: $width - $gutter-width;
  }
  @return $width;
}

// Returns the opposite direction, given "left" or "right".
// @see http://zengrids.com/help/#zen-direction-flip
@function zen-direction-flip(
  $dir
) {
  @if $dir == left {
    @return right;
  }
  @else if $dir == right {
    @return left;
  }
  @else if $dir == none or $dir == both {
    @return $dir;
  }
  @warn "Invalid direction passed to zen-direction-flip().";
  @return both;
}
