import * as THREE from 'three';

import invariant from 'fbjs/lib/invariant';
import PropTypes from 'react/lib/ReactPropTypes';

import THREEElementDescriptor from '../../THREEElementDescriptor';
import ShapeAction from '../../../Shapes/ShapeAction';
import propTypeInstanceOf from '../../../utils/propTypeInstanceOf';

class PathDescriptorBase extends THREEElementDescriptor {
  constructor(react3RendererInstance) {
    super(react3RendererInstance);

    this.hasProp('points', {
      type: PropTypes.arrayOf(propTypeInstanceOf(THREE.Vector2)),
      update: this.triggerRemount,
      default: [],
    });
  }

  applyInitialProps(threeObject, props) {
    threeObject.userData = {
      ...threeObject.userData,
    };

    // paths don't have uuids
    threeObject.uuid = THREE.Math.generateUUID();

    return super.applyInitialProps(threeObject, props);
  }

  addChildren(threeObject, children) {
    // TODO: create paths here

    if (process.env.NODE_ENV !== 'production') {
      invariant(children.filter(this._invalidChild).length === 0,
        'Shape children can only be shape actions!');
    } else {
      invariant(children.filter(this._invalidChild).length === 0, false);
    }

    // apply all actions in order
    children.forEach((child) => {
      this.performChildAction(threeObject, child);
    });
  }

  performChildAction(threeObject, child) {
    child.performAction(threeObject);
  }

  addChild(threeObject) {
    this.triggerRemount(threeObject);
  }

  moveChild(threeObject) {
    this.triggerRemount(threeObject);
  }

  removeChild(threeObject) {
    this.triggerRemount(threeObject);
  }

  _invalidChild = (child) => {
    const invalid = !(
      child instanceof ShapeAction
    );

    return invalid;
  };

  highlight(threeObject) {
    const parentObject = threeObject.userData.markup.parentMarkup.threeObject;

    parentObject.userData._descriptor.highlight(parentObject);
  }

  getBoundingBoxes(threeObject) {
    const parentObject = threeObject.userData.markup.parentMarkup.threeObject;

    return parentObject.userData._descriptor.getBoundingBoxes(parentObject);
  }
}

module.exports = PathDescriptorBase;
