///|
/// moonfig 示例:四层来源叠在一起,最后还能问出每个值来自哪一层。
///
/// 运行:`moon run examples/multi_source -- --log-level=debug`
///
/// 四层来源,按加入顺序(后加的赢):
///
/// 1. 内存默认值
/// 2. 配置文件 `examples/multi_source/config/app.json`
/// 3. 环境变量 `APP_DB_PORT` / `APP_DB_PASSWORD`
/// 4. 命令行参数 `--log-level=debug`
///
/// 环境变量这一层为了演示可复现,由程序自己设上;真实程序直接用进程里已有的
/// 环境变量,不需要这一段。

///|
using @config {type Config, type MemorySource, type Origin, type Value}

///|
using @jsonfmt {type JsonFormat}

///|
using @file_source {type FileSource}

///|
using @env_source {type EnvSource}

///|
using @cli_source {type CliSource}

///|
/// 演示用的环境变量:真实程序不用这一层
fn seed_env() -> Unit {
  @env.set_env_var("APP_DB_PORT", "6543")
  @env.set_env_var("APP_DB_PASSWORD", "s3cret")
}

///|
/// 演示结束后清掉,免得污染 shell
fn clear_env() -> Unit {
  @env.unset_env_var("APP_DB_PORT")
  @env.unset_env_var("APP_DB_PASSWORD")
}

///|
/// 组装四层来源
fn build_config() -> Config raise {
  let defaults = MemorySource::new(
    Value::table({
      "db": Value::table({
        "host": Value::str("localhost"),
        "port": Value::int(5432L),
      }),
      "log": Value::table({ "level": Value::str("info") }),
      "feature": Value::table({ "debug": Value::bool(false) }),
    }),
  )
  Config::new()
  .add(defaults)
  .add(
    FileSource::new("examples/multi_source/config/app.json", JsonFormat::new()),
  )
  .add(EnvSource::new("APP_"))
  .add(CliSource::new())
  .build()
}

///|
fn show(origin : Origin?) -> String {
  match origin {
    Some(origin) => "\{origin.label()}"
    None => "(no origin)"
  }
}

///|
fn main raise {
  seed_env()
  let cfg = build_config()

  println("== Effective values ==")
  println("db.host    = \{cfg.get_string("db.host")}")
  println("db.port    = \{cfg.get_int("db.port")}")
  println("db.password= \{cfg.get_string("db.password")}")
  println("log.level  = \{cfg.get_string("log.level")}")
  println("feature.debug = \{cfg.get_bool("feature.debug")}")

  println("")
  println("== Origin of each value ==")
  println("db.host       <- \{show(cfg.origin_of("db.host"))}")
  println("db.port       <- \{show(cfg.origin_of("db.port"))}")
  println("db.password   <- \{show(cfg.origin_of("db.password"))}")
  println("log.level     <- \{show(cfg.origin_of("log.level"))}")
  println("feature.debug <- \{show(cfg.origin_of("feature.debug"))}")

  println("")
  println("== What --print-config would list ==")
  let origins = cfg.origins()
  for origin in origins {
    println("\{origin.path().to_string()}  \{origin.label()}")
  }

  clear_env()
}