// `mctl template` — the bundled template library, described.
//
// A template is a directory of files with `{{.Name}}` holes in them, plus the rules
// mctl needs to fill them: which spec each kind reads, what it writes, and what a
// user has to rename. The catalogue lives here so `mctl template list` and `mctl
// template show` describe the same thing the generators use, and so a remote
// library (--remote, --branch) can be compared entry by entry.

///|
/// One template: the name a user types, the kind of spec it reads, one sentence on
/// what it produces, and the directory under the template home it lives in.
pub(all) struct TemplateEntry {
  name : String
  kind : String
  description : String
  path : String
}

///|
/// The bundled library, in the order it is listed.
pub fn templates() -> Array[TemplateEntry] {
  [
    {
      name: "api-service",
      kind: "api",
      description: "a moonapi service: routes, handlers, logic, config and a Dockerfile",
      path: "api/service",
    },
    {
      name: "api-flat",
      kind: "api",
      description: "the same routes and types in one .mbt file, for a small service",
      path: "api/flat",
    },
    {
      name: "rpc-service",
      kind: "proto",
      description: "a moonrpc service: messages, codecs, handler table and a client",
      path: "rpc/service",
    },
    {
      name: "gql-service",
      kind: "api",
      description: "a moongql schema and resolver over the spec's types",
      path: "gql/service",
    },
    {
      name: "mcp-server",
      kind: "api",
      description: "an MCP server whose tools are the spec's annotated handlers",
      path: "mcp/server",
    },
    {
      name: "model-mysql",
      kind: "ddl",
      description: "moonorm models and CRUD for a MySQL schema, reflected or from DDL",
      path: "model/mysql",
    },
    {
      name: "model-postgres",
      kind: "ddl",
      description: "moonorm models and CRUD for a PostgreSQL schema",
      path: "model/postgres",
    },
    {
      name: "model-mongo",
      kind: "api",
      description: "document models over a Mongo collection, with a typed collection port",
      path: "model/mongo",
    },
    {
      name: "gateway",
      kind: "proto",
      description: "an HTTP gateway that routes to a moonrpc client",
      path: "gateway/http",
    },
  ]
}

///|
/// The template called `name`, or `None`.
pub fn find_template(name : String) -> TemplateEntry? {
  for t in templates() {
    if t.name == name {
      return Some(t)
    }
  }
  None
}

///|
/// The templates of one kind — the ones a `gen` of that kind may pick.
pub fn templates_of(kind : String) -> Array[TemplateEntry] {
  let out : Array[TemplateEntry] = []
  for t in templates() {
    if t.kind == kind {
      out.push(t)
    }
  }
  out
}

///|
/// `mctl template list`: a table a reader scans rather than a paragraph they read.
pub fn template_table() -> String {
  let out : Array[String] = []
  out.push("| Template | Spec | What it produces |")
  out.push("| --- | --- | --- |")
  for t in templates() {
    out.push("| `" + t.name + "` | " + t.kind + " | " + t.description + " |")
  }
  @text.join_lines(out)
}

///|
/// `mctl template show `: one entry, and where it sits in the library.
pub fn template_detail(t : TemplateEntry) -> String {
  let out : Array[String] = []
  out.push("# " + t.name)
  out.push("")
  out.push(t.description + ".")
  out.push("")
  out.push("- reads: `." + t.kind + "`")
  out.push("- lives in: `" + t.path + "` under the template home")
  out.push("- override: put your own `" + t.path + "` under `--home `")
  @text.join_lines(out)
}