const READ_FLAGS = new Set(["read", "\\Seen", "Seen"])
const STARRED_FLAGS = new Set(["starred", "\\Flagged", "Flagged", "$Flagged"])
const IMPORTANT_FLAGS = new Set(["important", "\\Important", "$Important"])

function stripKnownFlags(flags: string[], known: Set<string>): string[] {
  return flags.filter((f) => !known.has(f))
}

export function mailFlagIsRead(flags: string[]): boolean {
  return flags.some((f) => READ_FLAGS.has(f))
}

export function mailFlagIsStarred(flags: string[]): boolean {
  return flags.some((f) => STARRED_FLAGS.has(f))
}

export function mailFlagIsImportant(flags: string[], labels: string[] = []): boolean {
  if (labels.some((l) => l.toLowerCase() === "important")) return true
  return flags.some((f) => IMPORTANT_FLAGS.has(f))
}

export function messageHasLabel(
  labels: string[] | null | undefined,
  label: string
): boolean {
  const needle = label.toLowerCase()
  return labels?.some((l) => l.toLowerCase() === needle) ?? false
}

export function messageHasFlag(
  flags: string[] | null | undefined,
  flag: string
): boolean {
  const needle = flag.toLowerCase()
  return flags?.some((f) => f.toLowerCase() === needle) ?? false
}

export function messageIsSpam(
  flags: string[] | null | undefined,
  labels?: string[] | null | undefined
): boolean {
  return messageHasFlag(flags, "spam") || messageHasLabel(labels, "spam")
}

export function mailFlagsWithRead(flags: string[], read: boolean): string[] {
  const next = stripKnownFlags(flags, READ_FLAGS)
  if (read) next.push("\\Seen")
  return next
}

export function mailFlagsWithStarred(flags: string[], starred: boolean): string[] {
  const next = stripKnownFlags(flags, STARRED_FLAGS)
  if (starred) next.push("\\Flagged")
  return next
}

export function mailFlagsWithImportant(flags: string[], important: boolean): string[] {
  const next = stripKnownFlags(flags, IMPORTANT_FLAGS)
  if (important) next.push("important")
  return next
}
