content: import React from 'react';
  import { isValid } from 'validators/number-validator';
  import { numericAscending } from 'utils/sort-util';
  import clone from 'clone';
  import TimeseriesLegendItem from 'components/timeseries-legend-item';
  import { getLayout } from 'layouts/flexbox';
  import getTranslate from 'decorators/get-translate';
  import setStateFromProps from 'decorators/set-state-from-props';
  import shouldComponentUpdate from 'decorators/should-component-update';
  import d3 from 'd3';
  
  @getTranslate
  @setStateFromProps
  @shouldComponentUpdate
  export default class TimeseriesLegend extends React.Component {
  
    static propTypes = {
      dispatcher: React.PropTypes.object.isRequired,
      groups: React.PropTypes.arrayOf(
        React.PropTypes.object
      ).isRequired,
      height: React.PropTypes.number.isRequired,
      width: React.PropTypes.number.isRequired,
      x: React.PropTypes.number.isRequired,
      y: React.PropTypes.number.isRequired,
    }
  
    static defaultProps = {
      dispatcher: d3.dispatch(),
      groups: [{series: []}],
      height: 0,
      width: 0,
      x: 0,
      y: 0,
    }
  
    state = {
      layout: {},
      series: [],
      translate: '',
    }
  
    componentDidMount() {
      this.setLayoutOnState(this.props);
    }
  
    componentDidUpdate() {
      this.setLayoutOnState(this.props);
    }
  
    getLayout(props) {
      const node = React.findDOMNode(this);
      if (node) {
        const childNodes = [].slice.call(node.childNodes);
        const childStyles = [];
        childNodes.forEach(() =>
          childStyles.push({style: {
            marginRight: Math.round(this.props.x / 2),
          }})
        );
        return getLayout(node, {
          alignItems: 'center',
          flexDirection: 'row',
          flexWrap: 'nowrap',
          height: props.height,
          justifyContent: 'flex-start',
          paddingLeft: Math.round(props.x / 4),
          width: props.width,
        }, childStyles);
      }
      return {};
    }
  
    getLegendItemX(layout, index) {
      if (layout && layout.children) {
        const child = layout.children[index];
        if (child) {
          return child.left;
        }
      }
      return 0;
    }
  
    getSeries(groups) {
      // FIXME: Surely this can be done more efficiently;
      // this is to support the optional legend index prop.
      const cloned = clone(groups);
  
      // If there's only one group, bail early:
      if (cloned.length < 2) {
        const group = cloned[0];
        return numericAscending(group.series, 'legendIndex');
      }
  
      // Pull all series out of groups into a single array:
      const series = cloned.reduce((previous, current) =>
        previous.series.concat(current.series)
      );
  
      // Ensure that all series have a valid index:
      series.forEach((datum, index) => {
        if (!isValid(datum.legendIndex)) {
          datum.legendIndex = index;
        }
      });
  
      // Sort series numerically on index:
      return numericAscending(series, 'legendIndex');
    }
  
    setLayoutOnState(props) {
      this.setState({
        layout: this.getLayout(props),
      });
    }
  
    setStateFromProps(props) {
      this.setState({
        series: this.getSeries(props.groups),
        translate: this.getTranslate(props.x, props.y),
      });
    }
  
    render() {
      return (
        <g
          className={'timeseries-legend'}
          transform={this.state.translate}>
          {this.state.series.map((datum, index) => (
            <TimeseriesLegendItem
              dispatcher={this.props.dispatcher}
              height={this.props.height}
              id={datum.id}
              interactive={datum.interactive}
              key={index}
              label={datum.legendLabel}
              series={datum}
              style={datum.style}
              type={datum.type}
              x={this.getLegendItemX(this.state.layout, index)} />
          ))}
        </g>
      );
    }
  
  }
  