import CameraControls from 'camera-controls';
import {
  Object3D,
  OrthographicCamera,
  PerspectiveCamera,
  Raycaster,
  Scene,
  Vector2,
  Vector3
} from 'three';
import { IObjectBaseConfig, IType } from './parkingLayer/index.type';

// let timer = 0
// export const reDraw = (time = 3000) => {
//   // @ts-ignore
//   CameraControls.viewChanged = true
//   clearTimeout(timer)
//   timer = setTimeout(() => {
//     // @ts-ignore
//     CameraControls.viewChanged = false
//   }, time)
// }

/**
 * @desc 射线拾取
 */
export function getIntersects({
  event,
  $map,
  scene,
  camera,
  objects
}: {
  event: any;
  $map: HTMLElement;
  scene: Scene;
  camera: PerspectiveCamera | OrthographicCamera;
  // 传入需要被射线拾取的物体
  objects?: Object3D[];
}) {
  const { top, left } = $map.getBoundingClientRect();
  // 声明raycaster和mouse变量
  const raycaster = new Raycaster();
  const mouse = new Vector2();
  // 通过鼠标点击的位置计算出raycaster所需要的点的位置，以屏幕中心为原点，值的范围为-1到1.
  mouse.x = ((event.clientX - left) / $map.clientWidth) * 2 - 1;
  mouse.y = -((event.clientY - top) / $map.clientHeight) * 2 + 1;
  // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
  raycaster.setFromCamera(mouse, camera);
  // 获取raycaster直线和所有模型相交的数组集合，注意：true表示返回的值会递归，找到更深层次的模型
  const intersects = raycaster.intersectObjects(
    objects || scene.children,
    true
  );

  // 2d 场景下会存在bug，就是选择点的时候，跑到中心点去了，数组第一个是对象 AxesHelper 导致的，这里进行过滤
  // intersects = intersects.filter(item => !(item.object instanceof AxesHelper))
  // if (filter) {
  //   intersects = filter(intersects)
  // }
  return intersects;
}

/**
 * @desc 射线拾取对象，获取世界坐标
 * objects 传入需要被射线拾取的物体。精准判断情况，不传入 objects， 获取被射线拾取的所有对象，然后再判断第一个对象是否被命中，即可判断当前是否点击了想要的对象。
 * @return 返回第一个点和所有被射线拾取的对象
 */
export function getWorldPosition({
  event,
  $map,
  scene,
  camera,
  objects
}: {
  event: any;
  $map: HTMLElement;
  scene: Scene;
  camera: PerspectiveCamera | OrthographicCamera;
  objects?: Object3D[];
}) {
  const intersects = getIntersects({ event, $map, scene, camera, objects });
  const points = intersects.map(item => item.point);
  const worldPosition = new Vector3();
  if (points.length > 0) {
    worldPosition.set(points[0].x, points[0].y, points[0].z);
    return { worldPosition, intersects };
  }
  return {};
}

/**
 * @desc 根据 name 获取对应的对象集合
 */
export function getObjectsByName<T = any>(
  name: string,
  parent: Object3D
): Array<T> {
  // scene.getObjectByName 只会返回第一个
  // return scene.getObjectByName(name);

  // 不能深层遍历
  // return scene.children.filter(item => item.name === name);
  // 较优算法
  const arr: any[] = [];
  parent.traverse(item => {
    if (item.name === name) arr.push(item);
  });
  return arr;
}

export function getPointBetweenPoints({
  p1,
  p2,
  // +1 把终点加入
  segment = Math.abs(
    Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
  ) + 1,
  // 从 0 开始，把起点加入
  i = 0
}: {
  p1: Vector3 | Vector2;
  p2: Vector3 | Vector2;
  segment?: number;
  i?: number;
}) {
  return {
    point: new Vector2(
      ((p2.x - p1.x) / segment) * i + p1.x,
      ((p2.y - p1.y) / segment) * i + p1.y
    ),
    segment
  };
}

/**
 * @desc 计算两个坐标连线后的倾斜角度
 */
export function getAngle(p1: Vector2 | Vector3, p2: Vector2 | Vector3) {
  const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x);
  const angle = radian * (180 / Math.PI);
  return {
    radian,
    angle
  };
}

export const CLS_PREFIX = 'ktmap';
