import React, { PureComponent, Children } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import './steps.scss'; // eslint-disable-line no-unused-vars


function calculateSelection(children) {
  let index = 0;
  let selectedStep = 0;
  let lastEnabled = 0;
  let resultValue = null;
  const arrayChildren = Children.toArray(children);
  arrayChildren.forEach(child => {
    const { type: { componentName }, props: { selected, enabled, value } } = child;
    if (componentName === 'Step') {
      if (selected) {
        selectedStep = index;
        lastEnabled = index;
        resultValue = value;
      } else if (enabled) {
        if (!resultValue) resultValue = value;
        lastEnabled = index;
      }
      index += 1;
    }
  });
  return { selectedStep, lastEnabled, value: resultValue };
}


class Steps extends PureComponent {
  static componentName = 'Steps';

  static propTypes = {
    children: PropTypes.node,
    variant: PropTypes.oneOf(['primary']),
    onChange: PropTypes.func,
    size: PropTypes.oneOf(['sm', 'md', 'lg']),
    /**
     * @ignore
     * if true on 'componentWillReceiveProps' children will be calculate
     */
    reCalculateSelection: PropTypes.bool,
    withBorder: PropTypes.bool,
    withRightArrow: PropTypes.bool,
    className: PropTypes.string
  };

  static defaultProps = {
    children: null,
    variant: 'primary',
    onChange: null,
    size: 'lg',
    reCalculateSelection: true,
    withBorder: false,
    withRightArrow: false,
    className: undefined
  };

  state = {
    selectedStep: 0,
    lastEnabled: 0,
    value: undefined,
    children: null
  };

  componentWillMount() {
    const { children, onChange, variant, size, withBorder, withRightArrow, className } = this.props;
    const { selectedStep, lastEnabled, value } = calculateSelection(children);
    const resultChildren = this.buildChildren({
      children, selectedStep, lastEnabled, variant, size, withBorder, withRightArrow, className
    });
    this.setState({
      selectedStep,
      lastEnabled,
      children: resultChildren
    });
    if (typeof onChange === 'function') {
      onChange(value);
    }
  }

  componentWillReceiveProps(nextProps) {
    const {
      children, onChange, reCalculateSelection, variant, size, withBorder, withRightArrow, className
    } = nextProps;
    if (reCalculateSelection) {
      const { selectedStep, lastEnabled, value } = calculateSelection(children);
      if (typeof onChange === 'function') {
        onChange(value);
      }
      const resultChildren = this.buildChildren({
        children, selectedStep, lastEnabled, variant, size, withBorder, withRightArrow, className
      });
      this.setState({
        selectedStep,
        lastEnabled,
        value,
        children: resultChildren
      });
    }
  }

  onStepClick = ({ index: selectedStep, value }) => {
    const { children, onChange, variant, size, withBorder, withRightArrow, className } = this.props;
    const { lastEnabled } = this.state;
    const resultChildren = this.buildChildren({
      children, selectedStep, lastEnabled, variant, size, withBorder, withRightArrow, className
    });
    this.setState({
      selectedStep,
      children: resultChildren
    });
    if (typeof onChange === 'function') {
      onChange(value);
    }
  };

  buildChildren({ children, selectedStep, lastEnabled, ...props }) {
    let childIndex = 0;
    return React.Children.map(children,
      child => {
        const { type: { componentName } } = child;
        if (componentName === 'Step') {
          const resultChild = React.cloneElement(child, {
            onClick: ({ index, value }) => {
              const { onClick } = child.props;
              this.onStepClick({ index, value });
              if (typeof onClick === 'function') {
                onClick({ index, value });
              }
            },
            enabled: lastEnabled >= childIndex,
            selected: selectedStep === childIndex,
            index: childIndex,
            lastEnabled: lastEnabled === childIndex,
            ...props
          });
          childIndex += 1;
          return resultChild;
        }
        return child;
      });
  }

  render() {
    const { children } = this.state;
    const { variant, size } = this.props;
    return (

      <div styleName={classNames(variant, `size-${size}`)}>
        {children}
      </div>
    );
  }
}


export default Steps;
