import type { Iwt2ArenaBounds, Iwt2Circle, Iwt2Vec2 } from './types'
import {
  addVec2,
  clamp,
  clampVec2ToArena,
  distanceVec2,
  dotVec2,
  lengthSqVec2,
  normalizeVec2,
  scaleVec2,
  subtractVec2,
} from './vector'

export function circlesOverlap(a: Iwt2Circle, b: Iwt2Circle): boolean {
  const radiusSum = a.radius + b.radius
  return distanceVec2(a.position, b.position) <= radiusSum
}

export function distanceToSegment(point: Iwt2Vec2, start: Iwt2Vec2, end: Iwt2Vec2): number {
  const segment = subtractVec2(end, start)
  const segmentLengthSq = lengthSqVec2(segment)
  if (segmentLengthSq <= 0.0001) return distanceVec2(point, start)
  const pointOffset = subtractVec2(point, start)
  const t = clamp(dotVec2(pointOffset, segment) / segmentLengthSq, 0, 1)
  const projection = addVec2(start, scaleVec2(segment, t))
  return distanceVec2(point, projection)
}

export function circleIntersectsSegment(
  circle: Iwt2Circle,
  start: Iwt2Vec2,
  end: Iwt2Vec2,
  width: number,
): boolean {
  return distanceToSegment(circle.position, start, end) <= circle.radius + width
}

export function separateCircles(moving: Iwt2Circle, fixed: Iwt2Circle, bounds: Iwt2ArenaBounds): Iwt2Vec2 {
  const offset = subtractVec2(moving.position, fixed.position)
  const minDistance = moving.radius + fixed.radius
  const distanceSq = lengthSqVec2(offset)
  if (distanceSq >= minDistance * minDistance) return moving.position
  const direction = distanceSq <= 0.0001 ? { x: 1, y: 0 } : normalizeVec2(offset)
  const resolved = addVec2(fixed.position, scaleVec2(direction, minDistance))
  return clampVec2ToArena(resolved, moving.radius, bounds)
}
