From f707c9ce984d579997e26e80ee46cc93499a7cec Mon Sep 17 00:00:00 2001
From: Jonathon Belotti <jonathon.bel.melbourne@gmail.com>
Date: Sun, 1 Sep 2019 12:07:55 +1000
Subject: [PATCH] implement 'add-to-shelf' command

---
 README.md   |  4 ++--
 src/main.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md
index de36be7..b490dd3 100644
--- a/README.md
+++ b/README.md
@@ -60,9 +60,9 @@ FLAGS:
     -V, --version    Prints version information
 
 SUBCOMMANDS:
-    add-to-shelf    Add a book to an existing shelf [In Progress]
+    add-to-shelf    Add a book to an existing shelf (eg. currently-reading, to-read)
     auth            Setup OAuth for the CLI (1 time only)
-    finished        Tell Goodreads you've finished a book you're currently reading
+    finished        Tell Goodreads you've finished a book that you're currently reading
     help            Prints this message or the help of the given subcommand(s)
     me              Show your User ID
     new             Tell Goodreads you've started a new book
diff --git a/src/main.rs b/src/main.rs
index 172b802..afce081 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -26,8 +26,13 @@ mod ux;
 #[structopt(raw(setting = "structopt::clap::AppSettings::ColoredHelp"))]
 enum Cli {
     #[structopt(name = "add-to-shelf")]
-    /// Add a book to an existing shelf [In Progress]
-    AddToShelf {},
+    /// Add a book to an existing shelf (eg. currently-reading, to-read)
+    AddToShelf {
+        #[structopt(short = "t", long = "title")]
+        title: Option<String>,
+        #[structopt(short = "s", long = "shelf")]
+        shelf: Option<String>,
+    },
     #[structopt(name = "me")]
     /// Show your User ID
     Me {},
@@ -38,7 +43,7 @@ enum Cli {
         title: Option<String>,
     },
     #[structopt(name = "update")]
-    /// Update progress on a book you're currently reading
+    /// Update progress on a book that you're currently reading
     Update {
         #[structopt(short = "t", long = "title")]
         title: Option<String>,
@@ -215,15 +220,51 @@ fn run_command(
     gr_client: &api_client::GoodreadsApiClient,
 ) -> BoxResult<()> {
     match args {
-        Cli::AddToShelf {} => {
-            // TODO(Jonathon): Stop hardcoding these
-            let res = gr_client.add_to_shelf(9282, "to-read");
+        Cli::AddToShelf { shelf, title } => {
+            let mut shelf_answer = String::new();
+            let mut title_answer = String::new();
+            let target_shelf = shelf.as_ref().unwrap_or_else(|| {
+                println!("❓: Which shelf would you like to add the book to?");
+                stdin()
+                    .read_line(&mut shelf_answer)
+                    .expect("Failed to read your input");
+                &shelf_answer
+            });
+            let title_query = title.as_ref().unwrap_or_else(|| {
+                println!("🔎 What's the title of the book?");
+                stdin()
+                    .read_line(&mut title_answer)
+                    .expect("Failed to read your input");
+                &title_answer
+            });
+            let res = gr_client
+                .search_books(&title_query, "title")
+                .and_then(|xml| {
+                    models::parse_book_search_results(&xml).map_err(|err| err.to_string())
+                })
+                .and_then(|results| {
+                    println!("📖 Results:");
+                    for (i, result) in results.iter().enumerate() {
+                        println!("{}. {} - {}", i + 1, result.1, result.2);
+                    }
+                    println!("\nWhich one is the one you'd like to add?");
+                    let choice = ux::get_choice(1, results.len() as u32)
+                        .map_err(|_err| "Failed to get user choice")?;
+                    let book_to_update = results
+                        .get((choice as usize) - 1)
+                        .expect("Should never access an invalid index here");
+                    Ok(book_to_update.0)
+                })
+                .and_then(|id| {
+                    gr_client.add_to_shelf(id, target_shelf)?;
+                    Ok(id)
+                });
             match res {
                 Ok(_) => {
-                    println!("Added ✅");
+                    println!("✅ Added to {}!", target_shelf);
                     Ok(())
                 }
-                Err(err) => bail!("fuck: {}", err),
+                Err(err) => bail!("Error: {}", err),
             }
         }
         Cli::New { title } => {
@@ -249,7 +290,7 @@ fn run_command(
                         .map_err(|_err| "Failed to get user choice")?;
                     let book_to_update = results
                         .get((choice as usize) - 1)
-                        .expect("Should never here access an invalid index");
+                        .expect("Should never access an invalid index here");
                     Ok(book_to_update.0)
                 })
                 .and_then(|id| {