import React, { Component } from 'react';
import withAnimationFrame from '@panter/react-animation-frame';
import { round, isFunction } from 'lodash';
import { NativeModules } from 'react-native';

const ARKitManager = NativeModules.ARKitManager;

const roundPoint = ({ x, y, z }, precision) => ({
  x: round(x, precision),
  y: round(y, precision),
  z: round(z, precision),
});

export default ({ throttleMs = 33 } = {}) => C =>
  withAnimationFrame(
    class extends Component {
      projectionRunning = true;
      _isMounted = false;
      constructor(props) {
        super(props);
        this.state = {
          positionProjected: props.position || { x: 0, y: 0, z: 0 },
          projectionResult: null,
        };
        this.handleAnimation(props);
      }
      componentWillMount() {
        this._isMounted = true;
      }
      handleAnimation({ projectionEnabled }) {
        if (projectionEnabled) {
          if (!this.projectionRunning) {
            this.projectionRunning = true;
            this.props.startAnimation();
          }
        } else if (this.projectionRunning) {
          this.projectionRunning = false;
          this.props.endAnimation();
        }
      }
      componentWillUpdate({ projectionEnabled = true }) {
        this.handleAnimation({ projectionEnabled });
      }

      componentWillUnmount() {
        this._isMounted = false;
      }

      onResult(result) {
        if (this._isMounted) {
          if (result) {
            this.setState({
              positionProjected: roundPoint(result.point, 3),
              projectionResult: result,
            });
          } else {
            this.setState({
              positionProjected: null,
              projectionResult: null,
            });
          }
          if (this.props.onProjectedPosition) {
            this.props.onProjectedPosition(result);
          }
        }
      }

      onAnimationFrame() {
        const { x, y, plane, node } = this.props.projectPosition || {};

        if (plane) {
          ARKitManager.hitTestPlanes(
            { x, y },
            ARKitManager.ARHitTestResultType.ExistingPlane,
          ).then(({ results }) => {
            const result = isFunction(plane)
              ? plane(results)
              : results.find(r => r.id === plane);
            this.onResult(result);
          });
        } else if (node) {
          ARKitManager.hitTestSceneObjects({ x, y }).then(({ results }) => {
            const result = isFunction(node)
              ? node(results)
              : results.find(r => r.id === node);
            this.onResult(result);
          });
        }
      }

      render() {
        return (
          <C
            positionProjected={this.state.positionProjected}
            projectionResult={this.state.projectionResult}
            {...this.props}
          />
        );
      }
    },
    throttleMs,
  );

@@ -406,16 +406,40 @@
 eMs = 33
+, overwritePosition = %7B%7D
  %7D = %7B%7D)
@@ -2745,16 +2745,35 @@
 jected=%7B
+%7B%0A              ...
 this.sta
@@ -2792,16 +2792,67 @@
 rojected
+,%0A              ...overwritePosition,%0A            %7D
 %7D%0A      

add option to overwwrite position