import React from 'react';
import classNames from 'classnames';

// Size of largest portion to give to smallest portion. We have a max of 5
// status types so we want to keep this growth ratio relatively small.
const GROW_RATIO = 0.07;
// Grow anything below this threshold by stealing from the biggest portion
const MIN_SIZE = 7; // (% of statusBar width)

function stealPortion(barSizes, indexesLessThanThreshold) {
  if (indexesLessThanThreshold.length) {
    // Try to steal some width from the largest portion
    // and give it to the first portion in indexesLessThanThreshold
    let maxSize = 0;
    let maxIndex = 0;
    // Find new Max (could be different after we've stolen from a portion already)
    barSizes.forEach(function (relativeSize, index) {
      if (relativeSize > maxSize) {
        maxSize = relativeSize;
        maxIndex = index;
      }
    });

    let currentGrowthIndex = indexesLessThanThreshold[0];
    let sizeToSteal = maxSize * GROW_RATIO;
    // Reassign the portion
    barSizes[currentGrowthIndex] += sizeToSteal;
    barSizes[maxIndex] -= sizeToSteal;

    if (barSizes[currentGrowthIndex] > MIN_SIZE) {
      // Done with growing this portion. Otherwise it stays on the stack
      // and will get another % added to it from the largest portion
      // calculated in the next iteration.
      indexesLessThanThreshold = indexesLessThanThreshold.slice(1);
    }
    // Recurse till we have grown everything above threshold
    stealPortion(barSizes, indexesLessThanThreshold);
  }
}

class StatusBar extends React.Component {
  getBars(data) {
    let max = data.reduce(function (sum, item) {
      return sum + item.value;
    }, 0);
    max = Math.max(this.props.scale, max);

    if (max === 0) {
      return null;
    }
    let indexesLessThanThreshold = [];

    let barSizes = data.map(function (status, index) {
      let {value} = status;

      let relativeSize = value / max * 100;

      if (relativeSize > 0 && relativeSize < MIN_SIZE) {
        indexesLessThanThreshold.push(index);
      }

      return relativeSize;
    });

    // Fudge barSizes to ensure small portions are visible
    stealPortion(barSizes, indexesLessThanThreshold);

    return data.map(function (status, index) {
      let {className} = status;
      let scale = barSizes[index];

      if (className == null) {
        className = `element-${index}`;
      }

      className = classNames(className, 'bar');

      if (scale === 0) {
        return null;
      }

      let style = {
        width: `${scale}%`
      };

      return (
        <div style={style} key={index} className={className}></div>
      );
    });
  }

  render() {
    let {data, className} = this.props;

    if (!data) {
      return null;
    }

    return (
      <div className={className}>{this.getBars(data)}</div>
    );
  }
}

StatusBar.defaultProps = {
  className: 'progress-bar flex-box upgrade-progress-bar status-bar',
  scale: null
};

StatusBar.propTypes = {
  className: React.PropTypes.string,
  scale: React.PropTypes.number,
  data: React.PropTypes.arrayOf(
    React.PropTypes.shape({
      className: React.PropTypes.string,
      value: React.PropTypes.number.isRequired
    })
  ).isRequired
};

module.exports = StatusBar;

@@ -407,20 +407,39 @@
 hreshold
+, unassignedPortion
 ) %7B%0A
-
   if (in
@@ -880,24 +880,200 @@
    %7D%0A    %7D);
+%0A    // Possible we have unassigned portion that we should steal from first%0A    if (unassignedPortion %3E maxSize) %7B%0A      maxSize = unassignedPortion;%0A      maxIndex = -1;%0A    %7D
 %0A%0A    let cu
@@ -1241,16 +1241,43 @@
 oSteal;%0A
+    if (maxIndex %3E -1) %7B%0A  
     barS
@@ -1306,16 +1306,75 @@
 ToSteal;
+%0A    %7D else %7B%0A      unassignedPortion -= sizeToSteal;%0A    %7D
 %0A%0A    if
@@ -1789,16 +1789,35 @@
 hreshold
+, unassignedPortion
 );%0A  %7D%0A%7D
@@ -1969,16 +1969,67 @@
  %7D, 0);%0A
+    let unassignedValue = this.props.scale - max;%0A%0A
     max 
@@ -2148,16 +2148,73 @@
 ld = %5B%5D;
+%0A    let unassignedPortion = unassignedValue / max * 100;
 %0A%0A    le
@@ -2594,16 +2594,35 @@
 hreshold
+, unassignedPortion
 );%0A%0A    
@@ -3368,20 +3368,17 @@
  scale: 
-null
+0
 %0A%7D;%0A%0ASta

Fix Stack overflow for case where statusbar is scaled