import { reactive } from 'vue'

const MIN_SCALE = 0.65
const MAX_SCALE = 2.4
const DEFAULT_SCALE = 1
const DEFAULT_TILT_X = 0.18
const DEFAULT_TILT_Y = -0.1
const DEFAULT_ORBIT_ANGLE = 0
const DEFAULT_DEPTH_STRENGTH = 1

export interface BrainViewportState {
  scale: number
  translateX: number
  translateY: number
  tiltX: number
  tiltY: number
  orbitAngle: number
  depthStrength: number
}

export function useBrainGraphViewport() {
  const viewport = reactive<BrainViewportState>({
    scale: DEFAULT_SCALE,
    translateX: 0,
    translateY: 0,
    tiltX: DEFAULT_TILT_X,
    tiltY: DEFAULT_TILT_Y,
    orbitAngle: DEFAULT_ORBIT_ANGLE,
    depthStrength: DEFAULT_DEPTH_STRENGTH,
  })

  function clampScale(nextScale: number) {
    return Math.min(MAX_SCALE, Math.max(MIN_SCALE, nextScale))
  }

  function clampTilt(value: number) {
    return Math.min(0.42, Math.max(-0.42, value))
  }

  function setScale(nextScale: number) {
    viewport.scale = clampScale(nextScale)
  }

  function zoomBy(multiplier: number) {
    setScale(viewport.scale * multiplier)
  }

  function panBy(deltaX: number, deltaY: number) {
    viewport.translateX += deltaX
    viewport.translateY += deltaY
  }

  function setTilt(nextTiltX: number, nextTiltY: number) {
    viewport.tiltX = clampTilt(nextTiltX)
    viewport.tiltY = clampTilt(nextTiltY)
  }

  function nudgeTilt(deltaX: number, deltaY: number) {
    setTilt(viewport.tiltX + deltaX, viewport.tiltY + deltaY)
  }

  function setOrbitAngle(nextAngle: number) {
    viewport.orbitAngle = nextAngle
  }

  function driftOrbit(delta: number) {
    viewport.orbitAngle += delta
  }

  function resetViewport() {
    viewport.scale = DEFAULT_SCALE
    viewport.translateX = 0
    viewport.translateY = 0
    viewport.tiltX = DEFAULT_TILT_X
    viewport.tiltY = DEFAULT_TILT_Y
    viewport.orbitAngle = DEFAULT_ORBIT_ANGLE
    viewport.depthStrength = DEFAULT_DEPTH_STRENGTH
  }

  return {
    viewport,
    driftOrbit,
    nudgeTilt,
    panBy,
    resetViewport,
    setOrbitAngle,
    setScale,
    setTilt,
    zoomBy,
  }
}
