// @flow weak
import React, { PureComponent } from 'react'; // eslint-disable-line no-unused-vars
import PropTypes from 'prop-types';
import transition from '../core/withTransitions/transition';
import stop from '../core/withTransitions/stop';
import { ENTER, UPDATE, EXIT } from '../core/types';

export const propTypes = {
  data: PropTypes.oneOfType([
    PropTypes.array, // NodeGroup data
    PropTypes.func,  // TickGroup scale
  ]),

  type: PropTypes.string.isRequired,
  udid: PropTypes.string.isRequired,
  node: PropTypes.object.isRequired,
  index: PropTypes.number.isRequired,

  start: PropTypes.func.isRequired,

  enter: PropTypes.func.isRequired,
  update: PropTypes.func.isRequired,
  leave: PropTypes.func.isRequired,

  render: PropTypes.func.isRequired,

  removeUDID: PropTypes.func.isRequired,
  lazyRemoveUDID: PropTypes.func.isRequired,
};

export default class Node extends PureComponent {
  static propTypes = propTypes;

  constructor(props) {
    super(props);

    (this:any).remove = this.remove.bind(this);
    (this:any).lazyRemove = this.lazyRemove.bind(this);
  }

  state = this.props.start(this.props.node, this.props.index);

  componentDidMount() {
    const { node, index, enter } = this.props;
    transition.call(this, enter(node, index, this.remove, this.lazyRemove));
  }

  componentWillReceiveProps(next) {
    const { props } = this;

    if (next.data !== props.data) {
      const { type, node, index, enter, update, leave } = next;

      switch (type) {
        case ENTER:
          transition.call(
            this,
            enter(node, index),
          );
          break;
        case UPDATE:
          transition.call(
            this,
            update(node, index),
          );
          break;
        case EXIT:
          transition.call(
            this,
            leave(node, index, this.remove, this.lazyRemove),
          );
          break;
        default:
          break;
      }
    }
  }

  componentWillUnmount() {
    stop.call(this);
  }

  remove() {
    const { removeUDID, udid } = this.props;
    removeUDID(udid);
  }

  lazyRemove() {
    const { lazyRemoveUDID, udid } = this.props;
    lazyRemoveUDID(udid);
  }

  render() {
    const { state, props: { node, index, render } } = this;

    return render(node, state, index);
  }
}

@@ -298,21 +298,67 @@
 %0Aexport 
-const
+default class Node extends PureComponent %7B%0A  static
  propTyp
@@ -364,16 +364,18 @@
 pes = %7B%0A
+  
   data: 
@@ -396,16 +396,18 @@
 fType(%5B%0A
+  
     Prop
@@ -437,24 +437,26 @@
 up data%0A    
+  
 PropTypes.fu
@@ -479,16 +479,18 @@
 p scale%0A
+  
   %5D),%0A%0A 
@@ -490,16 +490,18 @@
  %5D),%0A%0A  
+ 
+ 
 type: Pr
@@ -527,16 +527,18 @@
 quired,%0A
+  
   udid: 
@@ -566,16 +566,18 @@
 quired,%0A
+  
   node: 
@@ -605,16 +605,18 @@
 quired,%0A
+  
   index:
@@ -648,16 +648,18 @@
 red,%0A%0A  
+ 
+ 
 start: P
@@ -687,16 +687,18 @@
 red,%0A%0A  
+ 
+ 
 enter: P
@@ -723,16 +723,18 @@
 quired,%0A
+  
   update
@@ -762,16 +762,18 @@
 quired,%0A
+  
   leave:
@@ -797,24 +797,26 @@
 sRequired,%0A%0A
+  
   render: Pr
@@ -841,16 +841,18 @@
 uired,%0A%0A
+  
   remove
@@ -886,16 +886,18 @@
 ired,%0A  
+ 
+ 
 lazyRemo
@@ -935,92 +935,11 @@
 ed,%0A
-%7D;%0A%0Aexport default class Node extends PureComponent %7B%0A  static propTypes = propTypes
+  %7D
 ;%0A%0A 
@@ -1270,38 +1270,8 @@
 ndex
-, this.remove, this.lazyRemove
 ));%0A

move proptypes to static