///|
fn print_file(name : String, content : String) -> Unit {
  println("== " + name + " ==")
  println(content)
  println("")
}

///|
fn project_context_json() -> String {
  "{\"project\":{\"name\":\"moon-mustache-app\",\"port\":8080,\"network\":\"mustache-net\"},\"database\":{\"image\":\"postgres:16\",\"port\":5432},\"maintainer\":{\"name\":\"Alice\",\"email\":\"alice@example.com\"},\"features\":[\"config generation\",\"spec reporting\",\"CLI rendering\"]}"
}

///|
fn shared_partials() -> Map[String, String] {
  {
    "footer": "# Generated by moon-mustache\n",
    "feature_list": "{{#features}}- {{.}}\n{{/features}}",
  }
}

///|
fn scaffold_bundle() -> @src.TemplateBundle {
  let env_template =
    #|APP_NAME={{project.name}}
    #|APP_PORT={{project.port}}
    #|DB_HOST=db
    #|DB_PORT={{database.port}}
    #|MAINTAINER={{maintainer.email}}
    #|{{> footer}}
  let compose_template =
    #|services:
    #|  app:
    #|    image: {{project.name}}:latest
    #|    environment:
    #|      APP_PORT: {{project.port}}
    #|    ports:
    #|      - "{{project.port}}:{{project.port}}"
    #|    depends_on:
    #|      - db
    #|  db:
    #|    image: {{database.image}}
    #|    ports:
    #|      - "{{database.port}}:{{database.port}}"
    #|networks:
    #|  default:
    #|    name: {{project.network}}
  let readme_template =
    #|# {{project.name}}
    #|
    #|Maintainer: {{maintainer.name}} <{{maintainer.email}}>
    #|
    #|## Enabled Features
    #|{{> feature_list}}
    #|## Quick Start
    #|1. Start the stack with docker compose.
    #|2. Visit the service on port {{project.port}}.
    #|3. Extend the generated files with your own project logic.
    #|
    #|{{> footer}}
  let files = [
    @src.TemplateFile::new(".env", env_template),
    @src.TemplateFile::new("compose.yaml", compose_template),
    @src.TemplateFile::new("README.generated.md", readme_template),
  ]
  @src.TemplateBundle::new(files, shared_partials())
}

///|
fn main {
  let context_json = project_context_json()
  let result = @src.render_template_bundle_json_checked(
    scaffold_bundle(),
    context_json,
    @src.RenderOptions::strict(),
  )
  if @src.bundle_has_issues(result) {
    println("")
    for error in result.errors {
      println(error)
    }
    for name in result.missing_variables {
      println("missing variable: " + name)
    }
    return
  }
  for file in result.files {
    print_file(file.path, file.output)
  }
}