///|
/// ArkTS facade re-exporting the native module and every declared interface.
pub fn har_facade(module_name : String, declarations : String) -> String {
  let names : Array[String] = []
  for line in declarations.split("\n") {
    if line.has_prefix("export interface ") {
      let name = line[17:].to_owned().split(" ").head().unwrap_or("").to_owned()
      if identifier(name) && !names.contains(name) {
        names.push(name)
      }
    }
  }
  let library = "lib" + module_name + ".so"
  "// Generated by MoonOHOS " +
  moonohos_version() +
  " from types/" +
  "lib" +
  module_name +
  "/index.d.ts; regenerated by `moonohos har`.\nimport native from '" +
  library +
  "';\n\nexport { " +
  names.join(", ") +
  " } from '" +
  library +
  "';\nexport default native;\n"
}

///|
/// Checks a HAR module and points its native type dependency at the package.
pub fn har_package_manifest(
  text : String,
  module_name : String,
) -> String raise ConfigError {
  let json = @json.parse(text) catch {
    _ =>
      raise Invalid(
        "har: oh-package.json5 must be plain JSON (as created by moonohos init)",
      )
  }
  match json {
    Object(fields) => {
      match fields.get("main") {
        Some(String("Index.ets")) => ()
        _ => raise Invalid("har: oh-package.json5 main must be Index.ets")
      }
      let result = fields.copy()
      let dependencies : Map[String, Json] = match fields.get("dependencies") {
        Some(Object(values)) => values.copy()
        None => Map([])
        _ => raise Invalid("har: dependencies must be an object")
      }
      dependencies["lib" + module_name + ".so"] = ("file:./src/main/cpp/types/lib" +
      module_name).to_json()
      result["dependencies"] = dependencies.to_json()
      result.to_json().stringify(indent=2) + "\n"
    }
    _ => raise Invalid("har: oh-package.json5 must be an object")
  }
}

///|
pub fn validate_har_module(module_json : String) -> Unit raise ConfigError {
  let compact = module_json
    .replace_all(old=" ", new="")
    .replace_all(old="\n", new="")
    .replace_all(old="\r", new="")
    .replace_all(old="\t", new="")
  if !compact.contains("\"type\":\"har\"") {
    raise Invalid("har: src/main/module.json5 must declare \"type\": \"har\"")
  }
}

///|
/// Provenance written next to the libraries inside the HAR module.
pub fn har_provenance(
  manifest : PackageManifest,
  manifest_sha256 : String,
) -> Json {
  {
    "moonohosVersion": moonohos_version(),
    "module": manifest.module_name,
    "packageVersion": manifest.version,
    "manifestSha256": manifest_sha256,
    "abis": manifest.abis.to_json(),
    "files": manifest.files
    .filter(f => f.path.has_prefix("libs/") || f.path.has_prefix("types/"))
    .map(f => f.to_json())
    .to_json(),
  }
}