const LOW_MEMORY_LIMIT_GB = 4
const LOW_CPU_LIMIT = 4

function getNavigator() {
  if (typeof navigator === 'undefined') {
    return null
  }

  return navigator
}

function getUserAgent() {
  const nav = getNavigator()
  return nav?.userAgent || ''
}

export function isLowEndDevice() {
  const nav = getNavigator()

  if (!nav) {
    return false
  }

  const userAgent = getUserAgent()
  const deviceMemory = Number(nav.deviceMemory || 0)
  const hardwareConcurrency = Number(nav.hardwareConcurrency || 0)
  const isAndroid = /Android/i.test(userAgent)
  const androidVersionMatch = userAgent.match(/Android\s+(\d+)/i)
  const androidMajorVersion = androidVersionMatch ? Number(androidVersionMatch[1]) : 0

  return (
    (deviceMemory > 0 && deviceMemory <= LOW_MEMORY_LIMIT_GB) ||
    (isAndroid && hardwareConcurrency > 0 && hardwareConcurrency <= LOW_CPU_LIMIT) ||
    (isAndroid &&
      androidMajorVersion > 0 &&
      androidMajorVersion <= 9 &&
      hardwareConcurrency > 0 &&
      hardwareConcurrency <= LOW_CPU_LIMIT)
  )
}

export function prefersReducedMotion() {
  if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') {
    return false
  }

  return window.matchMedia('(prefers-reduced-motion: reduce)').matches
}

export function shouldUseLiteAnimations() {
  return isLowEndDevice() || prefersReducedMotion()
}

export function scheduleIdleTask(callback, timeout = 1200) {
  if (typeof window === 'undefined') {
    callback()
    return null
  }

  if (typeof window.requestIdleCallback === 'function') {
    return window.requestIdleCallback(callback, { timeout })
  }

  return window.setTimeout(callback, Math.min(timeout, 300))
}

export function cancelIdleTask(taskId) {
  if (typeof window === 'undefined' || taskId == null) {
    return
  }

  if (typeof window.cancelIdleCallback === 'function') {
    window.cancelIdleCallback(taskId)
    return
  }

  window.clearTimeout(taskId)
}

export function applyPerformanceModeClass(target) {
  const classTarget =
    target || (typeof document !== 'undefined' ? document.documentElement : null)

  if (!classTarget) {
    return
  }

  classTarget.classList.toggle('low-performance-mode', isLowEndDevice())
  classTarget.classList.toggle('reduce-motion-mode', prefersReducedMotion())
}
