import { map, takeWhile, drop, range, sum } from 'lodash';
import React from 'react';

import { PropTypes } from 'helpers/react';
const { string, number, shape, arrayOf, bool } = PropTypes;

import PaperImage from 'shared-components/PaperImage';

function aspectRatio({ width, height }) {
  return width / height;
}

function balancedRow(imagePool, idealHeight, containerWidth) { //-- returns the images, and the scale needed for them to fit in the width
  const images = [...imagePool];
  let resultHeight;

  let rowWidthAtIdealHeight = 0;
  const rowImages = takeWhile(images, (image) => {
    const imageAspectRatio = aspectRatio(image);
    const scaledImageWidth = idealHeight * imageAspectRatio;

    if (rowWidthAtIdealHeight < containerWidth) {
      rowWidthAtIdealHeight += scaledImageWidth;
      return true;
    }

    return false;
  });

  const rowAspectRatio = aspectRatio({ width: rowWidthAtIdealHeight, height: idealHeight });
  const rowHeightAtContainerWidth = containerWidth / rowAspectRatio;

  if (!(rowWidthAtIdealHeight >= containerWidth)) {
    // not enough images to fill the row; use ideal height and leave space, to avoid scaling the few images too large.
    resultHeight = idealHeight;
  } else if (images.length === 0) {
    // no images in pool; use 0 height to avoid NaN
    resultHeight = 0;
  } else {
    // otherwise use the calculated height to scale the combined row to container width
    resultHeight  = rowHeightAtContainerWidth;
  }

  return {
    images: rowImages,
    height: resultHeight
  };
}

export default function SceneGrid({
  sceneImage, sceneNeighborRows = 2, imagePool = [], width, margin = 10, sceneLeft, extraRowsIdealHeight = 150
}) {
  const containerWidth = width - 1; // stay 1 pixel away from the edge to prevent browser reflow bugs.
  let remainingImages = [...imagePool];

  const idealRowHeight = sceneImage.height / sceneNeighborRows;

  const neighborRows = range(sceneNeighborRows).map(_ => {
    const { images, height } = balancedRow(remainingImages, idealRowHeight, containerWidth);
    remainingImages = drop(remainingImages, images.length);

    return { images, height };
  });

  const combinedNeighborRowHeight = sum(map(neighborRows, 'height'));
  const sceneAspectRatio = aspectRatio(sceneImage);
  const scaledSceneWidth = combinedNeighborRowHeight * sceneAspectRatio;
  const fullCombinedWidth = scaledSceneWidth + containerWidth; // neighbor rows use full container width

  // what percentage smaller does the combined width of scene + neighbors need to be, to fit in the container width?
  const scaleFactor = containerWidth / fullCombinedWidth;

  const finalSceneImageWidth = scaledSceneWidth * scaleFactor || 0;
  const finalSceneImageHeight = (scaledSceneWidth / aspectRatio(sceneImage)) * scaleFactor || 0;

  return (
    <div style={ { 'lineHeight': 0, 'marginBottom': 20 } }>
      <div className="scene-image">
        <PaperImage style={ { float: sceneLeft ? 'left' : 'right' } }
                    margin={ margin }
                    height={ finalSceneImageHeight }
                    width={ finalSceneImageWidth }
                    src={ sceneImage.src }
        />
      </div>

      <div>
        {
          neighborRows.map(({ images, height }, i) => (
            <div key={ i }>
              {
                images.map(image => {
                  const imageHeight = height * scaleFactor;
                  const imageAspectRatio = aspectRatio(image);
                  const imageWidth = imageAspectRatio * height * scaleFactor;

                  return (
                    <PaperImage margin={ margin }
                                height={ imageHeight }
                                width={ imageWidth }
                                src={ image.src }
                                key={ image.src }
                    />
                  );
                })
              }
            </div>
          ))
        }
      </div>
      <div>
        <div className="grid">
          {
            range(remainingImages.length).map((i) => {
              if (remainingImages.length === 0) {
                return null;
              }

              const { images, height } = balancedRow(remainingImages, extraRowsIdealHeight, containerWidth);
              remainingImages = drop(remainingImages, images.length);

              return (
                <div key={ i }>
                  {
                    images.map(image => (
                      <PaperImage src={ image.src }
                                  height={ height }
                                  width={ aspectRatio(image) * height }
                                  margin={ margin }
                                  key={ image.src }
                      />
                    ))
                  }
                </div>
              );
            }).filter(Boolean)
          }
        </div>
      </div>
    </div>
  );
}

const imagePropType = shape({
  height: number,
  src: string,
  type: string,
  width: number
});

SceneGrid.propTypes = {
  sceneImage: imagePropType,
  sceneNeighborRows: number,
  imagePool: arrayOf(imagePropType),
  width: number,
  margin: number,
  sceneLeft: bool
};

@@ -3978,43 +3978,116 @@
 %3Cdiv
-%3E%0A        %3Cdiv className=%22grid%22%3E%0A  
+ style=%7B %7B marginTop: 5 %7D %7D%3E%0A        %7B /* margin required to prevent row above interfering with layout */ %7D%0A
     
@@ -4084,34 +4084,32 @@
  */ %7D%0A        %7B%0A
-  
           range(
@@ -4157,18 +4157,16 @@
         
-  
 if (rema
@@ -4191,24 +4191,87 @@
  === 0) %7B%0A  
+            // will be filtered out so we don't get extra divs%0A
             
@@ -4297,23 +4297,19 @@
         
-  
 %7D%0A%0A
-  
         
@@ -4419,18 +4419,16 @@
         
-  
 remainin
@@ -4480,34 +4480,32 @@
 );%0A%0A            
-  
 return (%0A       
@@ -4489,34 +4489,32 @@
        return (%0A
-  
               %3Cd
@@ -4535,38 +4535,34 @@
                 
- 
- 
 %7B%0A
-  
                 
@@ -4597,34 +4597,32 @@
                 
-  
 %3CPaperImage src=
@@ -4627,34 +4627,32 @@
 c=%7B image.src %7D%0A
-  
                 
@@ -4709,34 +4709,32 @@
                 
-  
 width=%7B aspectRa
@@ -4747,34 +4747,32 @@
 age) * height %7D%0A
-  
                 
@@ -4829,34 +4829,32 @@
                 
-  
 key=%7B image.src 
@@ -4867,39 +4867,35 @@
                 
- 
- 
 /%3E%0A
-  
                 
@@ -4907,38 +4907,34 @@
                 
-  %7D%0A  
+%7D%0A
               %3C/
@@ -4942,39 +4942,35 @@
 iv%3E%0A            
-  
 );%0A
-  
           %7D).fil
@@ -4994,26 +4994,9 @@
     
-  %7D%0A        %3C/div%3E
+%7D
 %0A   

use margin instead of a .grid class