var LayoutEngine = {}

LayoutEngine.generateRectangles = function (dimensionsArray, numColumns, totalWidth, gutter) {
  gutter = gutter || 0

  return dimensionsArray
    .map(scaleRectangles(numColumns, totalWidth, gutter))
    .map(translateRectanglesForNColumns(numColumns, totalWidth, gutter))
}

function translateRectanglesForNColumns(numColumns, totalWidth, gutter) {
  /* Translate rectangles into position */

  return function (rectangle, i, allRects) {
    if (!i) {
      // first round
      rectangle = placeRectangleAt(rectangle, 0, 0, gutter)
      return rectangle
    } else if (i < numColumns) {
      // first row
      rectangle = placeRectangleAt(rectangle, widthSingleColumn(numColumns, totalWidth, gutter) * i + gutter * i, 0, gutter)
      rectangle.flagged = false
      return rectangle
    } else {
      // place rects
      var placeAfter = placeAfterRectangle(allRects)
      rectangle = placeRectangleAt(rectangle, placeAfter.x, (placeAfter.height + placeAfter.y), gutter)
      placeAfter.flagged = true
      return rectangle
    }
  }
}

/* Scale all rectangles to fit into a single column */
function scaleRectangles (numColumns, totalWidth, gutter) {
  return function (rectangle) {
    var w = rectangle.width
    var h = rectangle.height
    
    var factor = w / h
    var width = widthSingleColumn(numColumns, totalWidth, gutter)
    var height = width / factor

    return {
      width: Math.floor(width),
      height: Math.floor(height),
      x: 0,
      y: 0,
      flagged: true,
    }  
  }
}

function placeRectangleAt (rectangle, x, y, gutter) {
  if (y) y += gutter

  return Object.assign(rectangle, {x: x, y: y, flagged: false})
}

/* Takes in a group of Rectangles and return the 'leading' rectangle */
function placeAfterRectangle (rectArray) {
  return rectArray
    .filter(function(r) {
      return !(r.flagged)
    })
    .reduce(function(prev, curr) {
      if (prev) {
        if (prev.height + prev.y < curr.height + curr.y) return prev
      }
      return curr
    })
}

function widthSingleColumn (numColumns, totalWidth, gutter) {
  return (totalWidth / numColumns) - gutter
}

if (typeof module === 'object' && module.exports) {
  module.exports = LayoutEngine
} else {
  window.LayoutEngine = LayoutEngine
}

@@ -169,16 +169,31 @@
    .map(
+LayoutEngine.__
 scaleRec
@@ -242,16 +242,31 @@
    .map(
+LayoutEngine.__
 translat
@@ -324,25 +324,31 @@
 er))%0A%7D%0A%0A
-function 
+LayoutEngine.__
 translat
@@ -361,32 +361,44 @@
 nglesForNColumns
+ = function 
 (numColumns, tot
@@ -550,32 +550,47 @@
     rectangle = 
+LayoutEngine.__
 placeRectangleAt
@@ -700,32 +700,47 @@
     rectangle = 
+LayoutEngine.__
 placeRectangleAt
@@ -751,16 +751,31 @@
 tangle, 
+LayoutEngine.__
 widthSin
@@ -957,16 +957,31 @@
 After = 
+LayoutEngine.__
 placeAft
@@ -1020,16 +1020,31 @@
 angle = 
+LayoutEngine.__
 placeRec
@@ -1244,25 +1244,31 @@
 lumn */%0A
-function 
+LayoutEngine.__
 scaleRec
@@ -1275,16 +1275,27 @@
 tangles 
+= function 
 (numColu
@@ -1454,16 +1454,31 @@
 width = 
+LayoutEngine.__
 widthSin
@@ -1691,25 +1691,31 @@
 %0A  %7D%0A%7D%0A%0A
-function 
+LayoutEngine.__
 placeRec
@@ -1723,16 +1723,27 @@
 angleAt 
+= function 
 (rectang
@@ -1923,25 +1923,31 @@
 ngle */%0A
-function 
+LayoutEngine.__
 placeAft
@@ -1958,16 +1958,27 @@
 ctangle 
+= function 
 (rectArr
@@ -2219,25 +2219,31 @@
   %7D)%0A%7D%0A%0A
-function 
+LayoutEngine.__
 widthSin
@@ -2252,16 +2252,27 @@
 eColumn 
+= function 
 (numColu

add private functions to namespace