import * as THREE from 'three';

/**
 * Shared bus between the main 3D viewer and the floating ViewCube widget.
 * - mainCameraRef / mainControlsRef: written by ModelViewer each frame
 * - requestView(dir): asks the main camera to animate to a canonical view
 *   along the given world-space direction (unit vector pointing FROM target
 *   TO camera). e.g. (0,1,0) = top view, (0,0,1) = front.
 */
export const mainCameraRef: { current: THREE.Camera | null } = { current: null };
// OrbitControls instance — typed loosely to avoid drei type churn
export const mainControlsRef: { current: any | null } = { current: null };

export interface ViewAnim {
  active: boolean;
  startPos: THREE.Vector3;
  endPos: THREE.Vector3;
  startUp: THREE.Vector3;
  endUp: THREE.Vector3;
  t: number;
  duration: number;
}

export const viewAnim: ViewAnim = {
  active: false,
  startPos: new THREE.Vector3(),
  endPos: new THREE.Vector3(),
  startUp: new THREE.Vector3(0, 1, 0),
  endUp: new THREE.Vector3(0, 1, 0),
  t: 0,
  duration: 0.5,
};

export function requestView(dir: THREE.Vector3) {
  const cam = mainCameraRef.current;
  const controls = mainControlsRef.current;
  if (!cam || !controls) return;
  const target: THREE.Vector3 = controls.target ?? new THREE.Vector3();
  const distance = cam.position.distanceTo(target);
  const d = dir.clone().normalize();
  const endPos = target.clone().add(d.multiplyScalar(distance));
  // Up vector: keep Y up unless we're looking straight up/down
  const up = new THREE.Vector3(0, 1, 0);
  if (Math.abs(dir.y) > 0.99) {
    up.set(0, 0, dir.y > 0 ? -1 : 1);
  }
  viewAnim.startPos.copy(cam.position);
  viewAnim.endPos.copy(endPos);
  viewAnim.startUp.copy(cam.up);
  viewAnim.endUp.copy(up);
  viewAnim.t = 0;
  viewAnim.active = true;
}
