/*:#localized(key: "SameJobRewritten")
 # The same job, written top-to-bottom

 Now the payoff. Here is the identical three-step job in the modern model. Read it
 straight down:
 */
//#-editable-code
import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

enum PrintError: Error {
    case designMissing, renderFailed, binderyJammed
}

func loadDesign(named name: String) async throws -> String {
    try await Task.sleep(for: .seconds(0.5))
    return "Design(\(name))"
}

func renderProof(from design: String) async throws -> Int {
    try await Task.sleep(for: .seconds(0.5))
    return 12
}

func bindBooklet(pageCount: Int) async throws -> String {
    try await Task.sleep(for: .seconds(0.5))
    return "Booklet(\(pageCount) pages)"
}

Task {
    do {
        let design  = try await loadDesign(named: "Spring Menu")
        let pages   = try await renderProof(from: design)
        let booklet = try await bindBooklet(pageCount: pages)
        print("✅ Ready: \(booklet)")
    } catch {
        print("❌ Failed: \(error)")
    }
    // The work is done (either way), so let the page stop.
    PlaygroundPage.current.finishExecution()
}
//#-end-editable-code
/*:#localized(key: "SameJobRewritten-2")
 **Watch it run:** same result, `✅ Ready: Booklet(12 pages)`, after the same wait.
 But hold the two versions side by side and feel the difference:

 * **It reads top-to-bottom.**  
 No nesting. Each step is a plain line, and the result of one flows into the next 
 like ordinary code. The pyramid is gone.
 * **Errors use `throws` and one `catch`.**  
 Three separate `.failure` branches collapse into a single `do-try-catch`. An error 
 at *any* step lands in the same place, and if you forget to handle it, the 
 compiler tells you.
 * **No lost callbacks.**  
 There's no completion handler to forget. Each `await` either produces a value or 
 throws; there is no path that silently drops.
 * **No manual `self` juggling in the middle** of the chain.  
 And (as you'll see in later chapters) a language-level way to say "this belongs 
 on the main thread" instead of hand-hopping queues.

 The word doing the heavy lifting is **`await`**: it marks a point where the
 function can *pause* until the result is ready, then continue on the next line,
 without blocking the thread while it waits. That's the whole trick, and it's the
 subject of the next chapter.

 * callout(Try it): Change `renderProof` to `return 24`. The chain still reads
 straight down, and the printed page count updates with no other edits: one value
 in, one value out.

 > Both versions do the same real work and wait the same real
 > time. Modern concurrency didn't make the print shop faster; it made the *code
 > that coordinates it* something you can read, and something the compiler helps you
 > get right.

 [Previous](@previous)  |  page 5 of 6  |  [Next: Wrapping Up](@next)
 */
