import React, { useState, useEffect } from "react";
import { View, StyleSheet, PanResponder } from "react-native";
import ExpoTHREE from "expo-three";
import ExpoGraphics from "expo-graphics";
import * as THREE from "three";
import UniCameraHandler from "./UniCameraHandler";
import { connect } from "react-redux";
import actions from "../../actions";
const mapDispatchToProps = (dispatch) => {
  return {
    reduxSetSingleShapeComponents: (components) => {
      dispatch(actions.setSingleCamera(components.camera));
      dispatch(actions.setSingleCameraHandler(components.cameraHandler));
      dispatch(actions.setSingleRenderer(components.renderer));
      dispatch(actions.setSingleScene(components.scene));
    },
  };
};
const mapStateToProps = (state) => {
  return {
    singleShapeComponents: state.singleShapeComponents,
  };
};
export default connect(mapStateToProps, mapDispatchToProps)(SingleShapeView);
function SingleShapeView(props) {
  const { shape, edges, points, newText, oldText, newTextGeo } = props;
  /*const [cameraHandler, setCameraHandler] = useState(null);
  const [renderer, setRenderer] = useState(null);
  const [camera, setCamera] = useState(null);
  const [scene, setScene] = useState(null);*/
  let clonePoints = points
    ? points.map((item) => {
        return {
          ...item,
          text: item.text.clone(),
        };
      })
    : [];
  useEffect(() => {
    //console.log(oldText);
    const shapePosition = shape.position;
    if (newText !== "" && oldText !== "" && newTextGeo) {
      const { scene, cameraHandler } = props.singleShapeComponents;
      for (let point of clonePoints) {
        //console.log(point.trueText);
        if (point.trueText === newText) {
          //console.log("found");
          const oldTexGeo = scene.getObjectByName(oldText);
          scene.remove(oldTexGeo);
          point.text = newTextGeo.clone();
          scene.add(point.text);
          let { x, y, z } = point.text.position;
          point.text.position.set(
            x - shapePosition.x,
            y - shapePosition.y,
            z - shapePosition.z
          );
          cameraHandler.addObjectsToTrack([point.text]);
          break;
        }
      }
    }
  }, [newText, newTextGeo, oldText]);

  const _transformEvent = (event) => {
    event.preventDefault = event.preventDefault || (() => {});
    event.stopPropagation = event.stopPropagation || (() => {});
    return event;
  };

  const handleStartShouldSetPanResponder = () => {
    return true;
  };

  // We were granted responder status! Let's update the UI
  const handlePanResponderGrant = (e, gestureState) => {
    const event = _transformEvent({ ...e, gestureState });
    const { cameraHandler } = props.singleShapeComponents;
    if (cameraHandler) cameraHandler.handlePanResponderGrant(event.nativeEvent);
  };

  // Every time the touch/mouse moves
  const handlePanResponderMove = (e, gestureState) => {
    // Keep track of how far we've moved in total (dx and dy)
    const event = _transformEvent({ ...e, gestureState });
    const { cameraHandler } = props.singleShapeComponents;
    cameraHandler.handlePanResponderMove(event.nativeEvent, gestureState);
  };

  // When the touch/mouse is lifted
  const handlePanResponderEnd = (e, gestureState) => {
    const { cameraHandler } = props.singleShapeComponents;
    const event = _transformEvent({ ...e, gestureState });
    cameraHandler.handlePanResponderEnd(event.nativeEvent);
  };
  const panResponder = PanResponder.create({
    onStartShouldSetPanResponder: handleStartShouldSetPanResponder,
    onPanResponderGrant: handlePanResponderGrant,
    onPanResponderMove: handlePanResponderMove,
    onPanResponderRelease: handlePanResponderEnd,
    onPanResponderTerminate: handlePanResponderEnd,
    onShouldBlockNativeResponder: () => false,
    onPanResponderTerminationRequest: () => true,
  });
  const fitCameraToObject = (camera, object) => {
    let offset = 4;

    const boundingBox = new THREE.Box3();

    // get bounding box of object - this will be used to setup controls and camera
    boundingBox.setFromObject(object);

    //const center = boundingBox.getCenter();

    const size = boundingBox.getSize();

    // get the max side of the bounding box (fits to width OR height as needed )
    const maxDim = Math.max(size.x, size.y, size.z);
    const fov = camera.fov * (Math.PI / 180);
    let cameraZ = Math.abs((maxDim / 4) * Math.tan(fov * 2));

    cameraZ *= offset; // zoom out a little so that objects don't fill the screen

    camera.position.z = cameraZ;

    const minZ = boundingBox.min.z;
    const cameraToFarEdge = minZ < 0 ? -minZ + cameraZ : cameraZ - minZ;

    camera.far = cameraToFarEdge * 3;
    camera.updateProjectionMatrix();
    return cameraZ;
  };

  const onContextCreate = ({ gl, width, height, scale }) => {
    console.log(points.length);
    let _renderer = new ExpoTHREE.Renderer({ gl });
    _renderer.setPixelRatio(scale);
    _renderer.setSize(width, height);
    _renderer.setClearColor(0x000000, 1.0);
    //console.log(renderer.domElement)

    let shapePosition = shape.position;
    const cloneShape = shape.clone();
    const cloneEdges = edges.clone();
    cloneShape.position.set(0, 0, 0);
    cloneEdges.position.set(0, 0, 0);
    let _scene = new THREE.Scene();
    let _camera = new THREE.PerspectiveCamera(70, width / height, 0.1, 10000);
    const baseDistance = 10; //fitCameraToObject(_camera, cloneShape);
    let _cameraHandler = new UniCameraHandler(_camera, baseDistance);
    for (let point of clonePoints) {
      const textGeo = point.text;
      textGeo.name = point.trueText;
      let { x, y, z } = textGeo.position;
      //console.log(cloneShape.position);
      textGeo.position.set(
        x - shapePosition.x,
        y - shapePosition.y,
        z - shapePosition.z
      );
      //console.log(textGeo.position);
      _scene.add(textGeo);
    }
    const axisHelper = new THREE.AxesHelper(200);
    cloneShape.add(axisHelper);
    _scene.add(cloneShape, cloneEdges);
    props.reduxSetSingleShapeComponents({
      cameraHandler: _cameraHandler,
      camera: _camera,
      renderer: _renderer,
      scene: _scene,
    });
  };

  const onRender = () => {
    let {
      cameraHandler,
      renderer,
      camera,
      scene,
    } = props.singleShapeComponents;
    cameraHandler.render(clonePoints);
    renderer.render(scene, camera);
  };

  return (
    <View
      {...panResponder.panHandlers}
      style={{
        flex: 1,
        borderWidth: 1,
        borderRadius: 5,
      }}
    >
      <ExpoGraphics.View
        // style={{ flex: 1 }}
        onContextCreate={(props) => {
          onContextCreate(props);
        }}
        onRender={(_props) => onRender(_props)}
        arEnabled={false}
        onShouldReloadContext={() => true}
      />
    </View>
  );
}