import React, { PropTypes } from "react";
import Helpers from "../victory-util/helpers";
import { assign, isEqual } from "lodash";
import * as d3Shape from "d3-shape";

export default class Area extends React.Component {
  static propTypes = {
    active: PropTypes.bool,
    className: PropTypes.string,
    data: PropTypes.array,
    events: PropTypes.object,
    groupComponent: PropTypes.element,
    interpolation: PropTypes.string,
    shapeRendering: PropTypes.string,
    role: PropTypes.string,
    scale: PropTypes.object,
    style: PropTypes.object
  };

  componentWillMount() {
    const {style, areaPath, linePath} = this.calculateAttributes(this.props);
    this.style = style;
    this.areaPath = areaPath;
    this.linePath = linePath;
  }


  shouldComponentUpdate(nextProps) {
    const {style, areaPath, linePath} = this.calculateAttributes(nextProps);
    if (areaPath === this.areaPath && linePath === this.linePath && isEqual(style, this.style)) {
      return false;
    } else {
      this.style = style;
      this.areaPath = areaPath;
      this.linePath = linePath;
      return true;
    }
  }

  calculateAttributes(props) {
    const {style, data, active} = props;
    return {
      style: Helpers.evaluateStyle(assign({fill: "black"}, style), data, active),
      areaPath: this.getAreaPath(props),
      linePath: this.getLinePath(props)
    };
  }

  toNewName(interpolation) {
    // d3 shape changed the naming scheme for interpolators from "basis" -> "curveBasis" etc.
    const capitalize = (s) => s && s[0].toUpperCase() + s.slice(1);
    return `curve${capitalize(interpolation)}`;
  }

  getAreaPath(props) {
    const xScale = props.scale.x;
    const yScale = props.scale.y;
    const areaFunction = d3Shape.area()
      .curve(d3Shape[this.toNewName(props.interpolation)])
      .x((data) => xScale(data.x1 || data.x))
      .y1((data) => yScale(data.y1 || data.y))
      .y0((data) => yScale(data.y0));
    return areaFunction(props.data);
  }

  getLinePath(props) {
    const xScale = props.scale.x;
    const yScale = props.scale.y;
    const lineFunction = d3Shape.line()
      .curve(d3Shape[this.toNewName(props.interpolation)])
      .x((data) => xScale(data.x1 || data.x))
      .y((data) => yScale(data.y1));
    return lineFunction(props.data);
  }

  // Overridden in victory-core-native
  renderArea(path, style, events) {
    const areaStroke = style.stroke ? "none" : style.fill;
    const areaStyle = assign({}, style, {stroke: areaStroke});
    const { role, shapeRendering, className } = this.props;
    return (
      <path
        key="area"
        style={areaStyle}
        shapeRendering={shapeRendering || "auto"}
        role={role || "presentation"}
        d={path}
        className={className}
        {...events}
      />
    );
  }

  // Overridden in victory-core-native
  renderLine(path, style, events) {
    if (!style.stroke || style.stroke === "none" || style.stroke === "transparent") {
      return undefined;
    }
    const { role, shapeRendering, className } = this.props;
    const lineStyle = assign({}, style, {fill: "none"});
    return (
      <path
        key="area-stroke"
        shapeRendering={shapeRendering || "auto"}
        style={lineStyle}
        role={role || "presentation"}
        d={path}
        className={className}
        {...events}
      />
    );
  }

  render() {
    const { events, groupComponent } = this.props;
    const area = this.renderArea(this.areaPath, this.style, events);
    const line = this.renderLine(this.linePath, this.style, events);
    return React.cloneElement(groupComponent, {}, area, line);
  }
}

@@ -1179,16 +1179,23 @@
 , active
+, scale
 %7D = prop
@@ -1193,24 +1193,472 @@
 e%7D = props;%0A
+    const xScale = scale.x;%0A    const yScale = scale.y;%0A    const interpolation = this.toNewName(props.interpolation);%0A    const areaFunction = d3Shape.area()%0A      .curve(d3Shape%5Binterpolation%5D)%0A      .x((d) =%3E xScale(d.x1 %7C%7C d.x))%0A      .y1((d) =%3E yScale(d.y1 %7C%7C d.y))%0A      .y0((d) =%3E yScale(d.y0));%0A    const lineFunction = d3Shape.line()%0A      .curve(d3Shape%5Binterpolation%5D)%0A      .x((d) =%3E xScale(d.x1 %7C%7C d.x))%0A      .y((d) =%3E yScale(d.y1));%0A
     return %7B
@@ -1760,71 +1760,61 @@
 th: 
-this.getAreaPath(props),%0A      linePath: this.getLinePath(props
+areaFunction(data),%0A      linePath: lineFunction(data
 )%0A  
@@ -2014,16 +2014,16 @@
 ice(1);%0A
+
     retu
@@ -2071,686 +2071,8 @@
  %7D%0A%0A
-  getAreaPath(props) %7B%0A    const xScale = props.scale.x;%0A    const yScale = props.scale.y;%0A    const areaFunction = d3Shape.area()%0A      .curve(d3Shape%5Bthis.toNewName(props.interpolation)%5D)%0A      .x((data) =%3E xScale(data.x1 %7C%7C data.x))%0A      .y1((data) =%3E yScale(data.y1 %7C%7C data.y))%0A      .y0((data) =%3E yScale(data.y0));%0A    return areaFunction(props.data);%0A  %7D%0A%0A  getLinePath(props) %7B%0A    const xScale = props.scale.x;%0A    const yScale = props.scale.y;%0A    const lineFunction = d3Shape.line()%0A      .curve(d3Shape%5Bthis.toNewName(props.interpolation)%5D)%0A      .x((data) =%3E xScale(data.x1 %7C%7C data.x))%0A      .y((data) =%3E yScale(data.y1));%0A    return lineFunction(props.data);%0A  %7D%0A%0A
   //

simplify area