import each from "lodash/each";
import isNumber from "lodash/isNumber";
import React from "react";

function isEmptyNode (node) {
  return node == null || node.type === "noscript";
}

export function mapNonEmpty(children, fn) {
  let offset = 0;
  return React.Children.map(children, function(child, index) {
    if (isEmptyNode(child)) {
      offset += 1;
      return child;
    }

    return fn(child, index - offset);
  });
}

export function forEachNonEmpty(children, fn) {
  let offset = 0;
  React.Children.forEach(children, function(child, index) {
    if (isEmptyNode(child)) {
      offset += 1;
      return;
    }

    fn(child, index - offset);
  });
}

export function countNonEmpty(children) {
  let count = 0;
  React.Children.forEach(children, function(child) {
    if (!isEmptyNode(child)) {
      count += 1;
    }
  });

  return count;
}

export function getVGutterSizes(children, defaultGutter) {
  return getGutterSizes('gutterTop', 'gutterBottom', children, defaultGutter);
}

export function getHGutterSizes(children, defaultGutter) {
  return getGutterSizes('gutterLeft', 'gutterRight', children, defaultGutter);
}

function getGutterSizes(gutterPrevKey, gutterNextKey, children, defaultGutter) {
  let childrenCount = countNonEmpty(children);
  let gutterSizes = new Array(childrenCount);

  // fill in gutters specified on children
  forEachNonEmpty(children, (child, index) => {
    let gutterPrev = child.props && child.props[gutterPrevKey],
        gutterNext = child.props && child.props[gutterNextKey];

    if (index === 0) {
      gutterSizes[0] = gutterPrev;
    } else {
      if (isNumber(gutterSizes[index])) {
        if (isNumber(gutterPrev)) {
          gutterSizes[index] = Math.max(gutterSizes[index], gutterPrev);
        }
      } else {
        gutterSizes[index] = gutterPrev;
      }
    }

    gutterSizes[index + 1] = gutterNext;
  });

  // fill in blank gutters with the default
  gutterSizes = gutterSizes.map((gutter, index) => {
    return isNumber(gutter) ? gutter :
      index === 0 || index === childrenCount ? 0 :
      defaultGutter;
  });

  return gutterSizes;
}



const sizeRegex = /^\s*(\d+)([^\s]+)\s*$/;

export function sumSizes(dimension, items) {
  const sum = {};

  items.forEach((item) => {
    const size = item.props[dimension] || (item.props.style && item.props.style[dimension]);
    if (size === undefined || size === null) { return; }
    if (isNumber(size)) {
      addTo(sum, 'px', size);
    } else {
      let matches = sizeRegex.exec(size);
      if (matches) {
        let [, value, unit] = matches;
        addTo(sum, unit, parseFloat(value));
      }
    }
  });

  return sum;
}

export function addTo(map, key, value) {
  if (!map[key]) {
    map[key] = value;
  } else {
    map[key] += value;
  }
}

export function getSizeCalc(usedSpace, flexGrow, totalFlexGrow) {
  const ratio = flexGrow / totalFlexGrow;
  const expressions = [`${100 * ratio}%`];

  each(usedSpace, (value, unit) => {
    expressions.push(`${value * ratio}${unit}`);
  });

  return `calc(${expressions.join(' - ')})`;
}

export function normalizeAlign(align) {
  let normalized;
  switch (align) {
    case "top":
      normalized = 'flex-start';
      break;
    case "middle":
      normalized = 'center';
      break;
    case 'bottom':
      normalized = 'flex-end';
      break;
    default:
      normalized = align;
      break;
  }

  return normalized;
}

export function normalizeJustify(justify) {
  switch (justify) {
    case "left":
      return 'flex-start';
    case "center":
      return 'center';
    case 'right':
      return 'flex-end';
  }
}

export function makeVLayoutItemChildProps(parentProps, childProps = {}, index, gutterSizes, gutterMultiplier) {
  var props = {};

  if (index === 0) {
    props._gutterTop = gutterSizes[0] ? gutterSizes[0] * gutterMultiplier + parentProps.gutterUnit : undefined;
  }
  props._gutterBottom = gutterSizes[index + 1] ? gutterSizes[index + 1] * gutterMultiplier + parentProps.gutterUnit : undefined;
  props.justify = childProps.justify || parentProps.justifyItems;

  return props;
}

export function makeHLayoutItemChildProps(parentProps, childProps = {}, index, gutterSizes, gutterMultiplier) {
  var props = {};

  if (index === 0) {
    props._gutterLeft = gutterSizes[0] ? gutterSizes[0] * gutterMultiplier + parentProps.gutterUnit : undefined;
  }
  props._gutterRight = gutterSizes[index + 1] ? gutterSizes[index + 1] * gutterMultiplier + parentProps.gutterUnit : undefined;
  props.align = childProps.align || parentProps.alignItems;

  return props;
}

export function didDefineWidth(props) {
  return props.width != null || (props.style && props.style.width) != null;
}

export function didDefineHeight(props) {
  return props.height != null || (props.style && props.style.height) != null;
}

export function pxToUnit(dimensionString) {
  if (!dimensionString) { return 0; }
  return parseInt(dimensionString.slice(0, -2), 10);
}
