// 能力探测与存在性判断:OPTIONS 探测服务端能力(DAV 等级 / Allow / Server),
// HEAD 不被支持时回落到 PROPFIND Depth:0 的 exists。单独成文件(RL-04)。

///|
/// 探测服务端能力(OPTIONS):返回 `DAV` 合规等级、`Allow` 方法列表与
/// `Server` 标识,便于在 LOCK / MKCOL / MOVE 等操作前判断服务端支持面,
/// 而不是靠失败状态码猜。
///
/// `path` 省略时探测根路径(服务端通常会回全局能力)。
pub async fn WebdavClient::options(
  self : WebdavClient,
  path? : String,
  signal? : @moonhttp.AbortSignal,
) -> @types.ServerCapabilities raise @types.WebdavError {
  let target = match path {
    Some(value) => value
    None => "/"
  }
  let response = self.send(
    operation="OPTIONS",
    http_method=@config.Method::Options,
    path=target,
    ok=[200, 204],
    signal?,
  )
  {
    dav_class: parse_dav_class(response.headers.get("DAV")),
    allow: parse_allow(response.headers.get("Allow")),
    server: response.headers.get("Server"),
  }
}

///|
/// 资源是否存在。
///
/// 优先用 HEAD(比 PROPFIND 轻,不返回响应体):200 / 204 存在、404 不存在、
/// 304 表示条件命中(资源存在且未变)。若服务端不支持 HEAD(405 / 501,
/// 部分对象存储与精简实现如此),回落到 PROPFIND Depth:0:207 存在、
/// 404 不存在。
pub async fn WebdavClient::exists(
  self : WebdavClient,
  path~ : String,
  conditions? : @types.Conditions,
  signal? : @moonhttp.AbortSignal,
) -> Bool raise @types.WebdavError {
  let response = self.send(
    operation="HEAD",
    http_method=@config.Method::Head,
    path~,
    conditions?,
    signal?,
    ok=[200, 204, 304, 404, 405, 501],
  )
  let status = response.status
  if status == 405 || status == 501 {
    return self.exists_by_propfind(path~, conditions?, signal?)
  }
  status == 200 || status == 204 || status == 304
}

///|
/// `exists` 的回退路径:PROPFIND Depth:0,207 视为存在、404 视为不存在。
async fn WebdavClient::exists_by_propfind(
  self : WebdavClient,
  path~ : String,
  conditions? : @types.Conditions,
  signal? : @moonhttp.AbortSignal,
) -> Bool raise @types.WebdavError {
  let outcome : Result[Unit, @types.WebdavError] = try {
    ignore(
      self.send_propfind(
        path~,
        depth=@types.Depth::Zero,
        body=@xmlutil.propfind_allprop_body(),
        conditions?,
        signal?,
      ),
    )
    Ok(())
  } catch {
    error => Err(error)
  }
  match outcome {
    Ok(_) => true
    Err(error) =>
      match error.detail() {
        Api(status=404, operation=_, message=_) => false
        _ => raise error
      }
  }
}

///|
/// 解析 `DAV` 响应头(形如 `1, 2` 或 `1,2` 或 `1, 2, extended-mkcol`)
/// 里的合规等级数字,非数字 token 忽略。
/// 没有该头时按 RFC 4918 §10.1 视为 Class 1。
fn parse_dav_class(header : String?) -> Array[Int32] {
  let levels : Array[Int32] = []
  match header {
    Some(text) =>
      for segment in text.split(",") {
        match @types.parse_ascii_int(segment.trim().to_owned()) {
          Some(level) => levels.push(level)
          None => ()
        }
      }
    None => ()
  }
  if levels.length() == 0 {
    levels.push(1)
  }
  levels
}

///|
/// 解析 `Allow` 响应头的方法名列表:去空白、ASCII 大写,保持出现顺序。
fn parse_allow(header : String?) -> Array[String] {
  let methods : Array[String] = []
  match header {
    Some(text) =>
      for segment in text.split(",") {
        let item = segment.trim()
        if item.length() > 0 {
          methods.push(@types.ascii_upper(item.to_owned()))
        }
      }
    None => ()
  }
  methods
}