// Notes in CouchDB: revisions and conflicts, a merge that retries, a bulk write read document by
// document, Mango queries paged by bookmark, and the changes feed carried on from a saved place.
//
//   COUCHDB_API_URL=http://localhost:5984 COUCHDB_USER=admin COUCHDB_PASSWORD=... quillo run couchdb.qwe
//   then open /setup, /revisions, /merge, /bulk, /find, /changes, /conflict and /broken

use "couchdb.qwer"

route GET /setup = {
    made: couchdb_create_db("notes")?,
    again: couchdb_create_db("notes")?,
    index: couchdb_create_index("notes", ["kind", "day"], "by-kind")?.result,
}

route GET /revisions {
    let first = couchdb_put("notes", "n1", { text: "one", kind: "todo", day: 1 })?
    let doc = couchdb_get("notes", "n1", "")?
    let second = couchdb_put("notes", "n1", { _rev: doc._rev, text: "two", kind: "todo", day: 1 })?
    {
        generation: split(second.rev, "-")[0],
        old_text: couchdb_get("notes", "n1", first.rev)?.text,
        stale: couchdb_put("notes", "n1", { _rev: first.rev, text: "late" }).error,
        no_rev: couchdb_put("notes", "n1", { text: "blind" }).error,
    }
}

route GET /merge = {
    merged: couchdb_merge("notes", "n1", { pinned: true })?.tries,
    fields: couchdb_get("notes", "n1", "")?.pinned,
    slash: couchdb_put("notes", "a/b c", { text: "odd id", kind: "misc", day: 9 })?.id,
    slash_read: couchdb_get("notes", "a/b c", "")?.text,
    none: couchdb_get("notes", "nothing", "")?,
}

// The third document is a conflict; the others go in anyway.
route GET /bulk {
    let r = couchdb_bulk("notes", [
        { _id: "n2", text: "two", kind: "todo", day: 2 },
        { _id: "n3", text: "three", kind: "todo", day: 3 },
        { _id: "n1", text: "no rev given" },
        { _id: "n4", text: "four", kind: "todo", day: 4 },
    ], null)?
    { written: len(r.ok), conflicts: r.conflicts, failed: r.failed }
}

route GET /find {
    let one = couchdb_find("notes", { kind: "todo", day: { "$gte": 2 } }, { sort: [{ day: "desc" }], fields: ["_id", "day"], limit: 2 })?
    let all = couchdb_find_all("notes", { kind: "todo" }, { limit: 2, sort: [{ day: "asc" }], fields: ["_id"] }, 100)?
    let cut = couchdb_find_all("notes", { kind: "todo" }, { limit: 1 }, 2)?
    { page: one.docs, ids: all.docs | map((d) => d._id), complete: all.complete, cut: cut.complete, bad: couchdb_find("notes", { kind: { "$nonsense": 1 } }, null).error }
}

route GET /changes {
    let first = couchdb_changes("notes", "0", { limit: 2, include_docs: true })?
    let rest = couchdb_changes("notes", first.last_seq, null)?
    couchdb_put("notes", "n9", { text: "new", kind: "misc", day: 10 })?
    let more = couchdb_changes("notes", rest.last_seq, null)?
    let doc = couchdb_get("notes", "n9", "")?
    couchdb_delete("notes", "n9", doc._rev)?
    {
        first: len(first.changes),
        pending: first.pending,
        rest: len(rest.changes),
        more: more.changes | map((c) => c.id),
        deleted: couchdb_changes("notes", more.last_seq, null)?.changes[0].deleted,
        selected: couchdb_changes("notes", "0", { selector: { kind: "misc" } })?.changes | map((c) => c.id),
        gone: couchdb_get("notes", "n9", "")?,
    }
}

// Two replicas changed one note: it now has two revisions, then one again.
route GET /conflict {
    couchdb_bulk("notes", [
        { _id: "shared", _rev: "2-aaaa", text: "from the phone" },
        { _id: "shared", _rev: "2-bbbb", text: "from the laptop" },
    ], { new_edits: false })?
    let c = couchdb_conflicts("notes", "shared")?
    let done = couchdb_resolve("notes", "shared", { text: "from both" })?
    {
        winner: c.winner.text,
        loser: c.losers | map((d) => d.text),
        removed: done.removed,
        after: couchdb_conflicts("notes", "shared")?,
        text: couchdb_get("notes", "shared", "")?.text,
    }
}

route GET /broken = {
    no_db: couchdb_get("no_such_db", "x", "").error,
    bad_name: couchdb_create_db("Upper Case").error,
    no_rev: couchdb_delete("notes", "n1", "").error,
    stale_delete: couchdb_delete("notes", "n1", "1-0000").error,
}
