import globToRegExp from "glob-to-regexp"
import { partition } from "lodash"
import { RuleType } from "./enums.generated"
import type { File, Rule } from "./index"

export * from "./enums.generated"

export function fileMatches(file: File, url: string) {
  const [includes, excludes] = partition(file.rules, rule => !rule.exclude)
  return (
    includes.some(rule => ruleMatches(rule, url)) &&
    excludes.every(rule => !ruleMatches(rule, url))
  )
}

function ruleMatches(rule: Rule, url: string) {
  switch (rule.type) {
    case RuleType.URL:
      return rule.value.includes(url)
    case RuleType.URLPrefix:
      return url.startsWith(rule.value)
    case RuleType.Domain:
      return getDomains(url).includes(rule.value)
    case RuleType.Glob:
      return globToRegExp(rule.value).test(url)
    case RuleType.RegExp:
      return toRegExp(rule.value).test(url)
  }
}

function getDomains(url: string): string[] {
  const { hostname } = new URL(url)

  const domains: string[] = [hostname]
  let index = hostname.indexOf(".")
  while (index !== -1) {
    domains.push(hostname.substring(index + 1))
    index = hostname.indexOf(".", index + 1)
  }

  return domains
}

function toRegExp(value: string) {
  // we want to match the full url, so add ^ and $ if not already present
  if (value[0] !== "^") value = `^${value}`
  if (!value.endsWith("$")) value += "$"
  return RegExp(value)
}
