// utils.ts
import type { Vector, GameConfig } from "./types"

// Vector utility functions
export const createVector = (x: number, y: number): Vector => ({ x, y })

export const vectorOps = {
  copy: (v: Vector): Vector => createVector(v.x, v.y),

  add: (v1: Vector, v2: Vector): Vector =>
    createVector(v1.x + v2.x, v1.y + v2.y),

  subtract: (v1: Vector, v2: Vector): Vector =>
    createVector(v1.x - v2.x, v1.y - v2.y),

  multiply: (v: Vector, scalar: number): Vector =>
    createVector(v.x * scalar, v.y * scalar),

  length: (v: Vector): number => Math.sqrt(v.x * v.x + v.y * v.y),

  normalize: (v: Vector): Vector => {
    const len = vectorOps.length(v)
    return len > 0 ? vectorOps.multiply(v, 1 / len) : createVector(0, 0)
  },

  rotate: (v: Vector, angle: number): Vector =>
    createVector(
      v.x * Math.cos(angle) - v.y * Math.sin(angle),
      v.x * Math.sin(angle) + v.y * Math.cos(angle),
    ),

  angle: (v: Vector): number => Math.atan2(v.y, v.x),

  setLength: (v: Vector, length: number): Vector =>
    vectorOps.multiply(vectorOps.normalize(v), length),

  distance: (v1: Vector, v2: Vector): number =>
    vectorOps.length(vectorOps.subtract(v1, v2)),
}

// Safe window access with fallbacks
export const getWindowDimensions = () => {
  if (typeof window === "undefined") {
    return { width: 1024, height: 768 } // Fallback dimensions for SSR
  }
  return {
    width: window.innerWidth,
    height: window.innerHeight,
  }
}

// Game configuration with SSR-safe initialization
export const createConfig = (): GameConfig => {
  const dimensions = getWindowDimensions()
  const cellSize = 100 // Grid cell size for spatial partitioning

  return {
    canvas: {
      width: dimensions.width,
      height: dimensions.height,
    },
    player: {
      acceleration: 300,
      maxSpeed: 400,
      rotationSpeed: 4,
      size: 12,
      thrustParticles: true,
    },
    bullets: {
      speed: 500,
      lifetime: 2000,
      fireRate: 150,
      maxCount: 15,
      size: 3,
    },
    particles: {
      speed: 200,
      lifetime: 1000,
      count: 8,
      colors: ["#ff0040", "#ffff00", "#ff8000", "#ff0080"],
    },
    enemies: {
      updateInterval: 300,
      ignoredTags: new Set([
        "HTML",
        "HEAD",
        "BODY",
        "SCRIPT",
        "TITLE",
        "CANVAS",
        "META",
        "STYLE",
        "LINK",
      ]),
      hiddenTags: new Set(["BR", "HR"]),
    },
    grid: {
      cellSize,
      cols: Math.ceil(dimensions.width / cellSize),
      rows: Math.ceil(dimensions.height / cellSize),
    },
    fps: 60,
  }
}

// Utility functions
export const toRadians = (degrees: number): number => (degrees * Math.PI) / 180
export const toDegrees = (radians: number): number => (radians * 180) / Math.PI
export const random = (min: number, max: number): number =>
  Math.random() * (max - min) + min
export const clamp = (value: number, min: number, max: number): number =>
  Math.max(min, Math.min(max, value))

// DOM utilities with null checks
export const createElement = (
  tag: string,
  className?: string,
  styles?: Partial<CSSStyleDeclaration>,
): HTMLElement => {
  if (typeof document === "undefined") {
    throw new Error(
      "Document not available - cannot create elements during SSR",
    )
  }

  const element = document.createElement(tag)
  if (className) element.className = className
  if (styles) Object.assign(element.style, styles)
  return element
}

export const hasOnlyTextualChildren = (
  element: HTMLElement,
  CONFIG: GameConfig,
): boolean => {
  if (CONFIG.enemies.hiddenTags.has(element.tagName)) return false
  if (element.offsetWidth === 0 && element.offsetHeight === 0) return false

  return Array.from(element.childNodes).every(
    (node) =>
      node.nodeType === Node.TEXT_NODE ||
      (node.nodeType === Node.ELEMENT_NODE &&
        CONFIG.enemies.hiddenTags.has((node as Element).tagName) &&
        (node as Element).childNodes.length === 0),
  )
}

// Game mechanics
export const wrapPosition = (position: Vector, CONFIG: GameConfig): Vector => ({
  x:
    position.x < 0
      ? CONFIG.canvas.width
      : position.x > CONFIG.canvas.width
        ? 0
        : position.x,
  y:
    position.y < 0
      ? CONFIG.canvas.height
      : position.y > CONFIG.canvas.height
        ? 0
        : position.y,
})
