///|
/// Return the final effective host name, if the configuration set one.
pub fn ResolvedConfig::hostname(self : ResolvedConfig) -> String? {
  match self.get("hostname") {
    Some(value) => Some(value.expanded)
    None => None
  }
}

///|
/// Return the final remote user selected by a supported `User` directive.
pub fn ResolvedConfig::user(self : ResolvedConfig) -> String? {
  match self.get("user") {
    Some(value) => Some(value.expanded)
    None => None
  }
}

///|
/// Return the selected port after the resolver's P0 range validation.
pub fn ResolvedConfig::port(self : ResolvedConfig) -> Int? {
  match self.get("port") {
    Some(value) => {
      let parsed : Int = @strconv.from_str(value.expanded) catch { _ => -1 }
      if parsed >= 1 && parsed <= 65535 {
        Some(parsed)
      } else {
        None
      }
    }
    None => None
  }
}

///|
/// Return all effective identity file values in their configuration order.
pub fn ResolvedConfig::identity_files(
  self : ResolvedConfig,
) -> Array[ResolvedValue] {
  self.get_all("identityfile")
}

///|
/// Project active `SetEnv` entries to their environment variable names.
/// The returned map contains immutable result values with source provenance;
/// callers cannot mutate resolver state by changing it.
pub fn ResolvedConfig::set_env(
  self : ResolvedConfig,
) -> Map[String, ResolvedValue] {
  let variables : Map[String, ResolvedValue] = Map([])
  for value in self.get_all("setenv") {
    match value.raw.find("=") {
      Some(index) if index > 0 => {
        let name = value.raw[:index].to_owned()
        let raw_value = value.raw[index + 1:].to_owned()
        let expanded_value = match value.expanded.find("=") {
          Some(expanded_index) => value.expanded[expanded_index + 1:].to_owned()
          None => value.expanded
        }
        variables[name] = {
          ..value,
          value: expanded_value,
          raw: raw_value,
          expanded: expanded_value,
        }
      }
      _ => ()
    }
  }
  variables
}

///|
/// Return true when at least one final value is present for `keyword`.
pub fn ResolvedConfig::contains(
  self : ResolvedConfig,
  keyword : String,
) -> Bool {
  self.get(keyword) is Some(_)
}