///|
/// Select one of the conventional pkg-config compiler or linker flag groups.
pub(all) enum FlagSelection {
  IncludePaths
  OtherCflags
  LibraryPaths
  Libraries
  OtherLibs
} derive(Eq, @debug.Debug)

///|
/// Keep selected arguments in their original order, with origins and diagnostics.
///
/// Split options retain their operands when both come from the same field.
/// IncludePaths selects -I, while OtherCflags retains -isystem and other options.
/// LibraryPaths selects -L, Libraries selects -l, and OtherLibs retains the rest.
/// GNU linker start/end groups remain intact in OtherLibs.
/// The returned flags are compiler arguments, including their option prefixes.
pub fn FlagResult::select(
  self : FlagResult,
  selection : FlagSelection,
) -> FlagResult {
  let flags : Array[ResolvedFlag] = []
  let mut i = 0
  while i < self.flags.length() {
    let flag = self.flags[i]
    let include_path = flag.value.has_prefix("-I")
    let library_path = flag.value.has_prefix("-L")
    // pkgconf treats MSVC's -lib: spelling as an opaque argument.
    let library = flag.value.has_prefix("-l") && !flag.value.has_prefix("-lib:")
    let keep = match selection {
      IncludePaths => include_path
      OtherCflags => !include_path
      LibraryPaths => library_path
      Libraries => library
      OtherLibs => !library_path && !library
    }
    let end = flag_group_end(self.flags, i)
    if keep {
      for j = i; j < end; j = j + 1 {
        flags.push(self.flags[j])
      }
    }
    i = end
  }
  { flags, diagnostics: self.diagnostics.copy(), }
}

///|
fn flag_group_end(flags : Array[ResolvedFlag], start : Int) -> Int {
  let first = flags[start]
  let mut end = start + 1
  if first.value == "-Wl,--start-group" {
    let mut depth = 1
    while end < flags.length() && same_flag_origin(first, flags[end]) {
      let value = flags[end].value
      end = end + 1
      if value == "-Wl,--start-group" {
        depth = depth + 1
      } else if value == "-Wl,--end-group" {
        depth = depth - 1
        if depth == 0 {
          break
        }
      }
    }
  } else if option_takes_operand(first.value) &&
    end < flags.length() &&
    same_flag_origin(first, flags[end]) {
    end = end + 1
  }
  end
}

///|
fn option_takes_operand(value : String) -> Bool {
  match value {
    "-I"
    | "-L"
    | "-l"
    | "-isystem"
    | "-idirafter"
    | "-iquote"
    | "-include"
    | "-imacros"
    | "-framework"
    | "-Xlinker"
    | "-Xassembler"
    | "-Xpreprocessor"
    | "-arch" => true
    _ => false
  }
}