package com.google.sps.data;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.sps.data.Book;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class GenreRecommender {
  private List<Book> books;
  private Map<Book, Set<String>> bookToGenres;
  private Map<String, Set<Book>> genreToBooks;

  /**
   * Constructor that takes in a list of books
   * and populates class variables appropriately.
   *
   * @param books: List of Book objects for the recommendation algorithm
   */
  public GenreRecommender(List<Book> books) {
    this.books = books;
    bookToGenres = new HashMap<Book, Set<String>>();
    genreToBooks = new HashMap<String, Set<Book>>();
    for (Book book : books) {
      Set<String> genres = book.genre();
      bookToGenres.put(book, genres);
      for (String genre : genres) {
        if (genreToBooks.containsKey(genre)) {
          genreToBooks.get(genre).add(book);
        } else {
          genreToBooks.put(genre, Sets.newHashSet(book));
        }
      }
    }
  }

  /**
   * Takes in a Book object and returns a set of genres
   * of that book
   *
   * @param book: Book object
   * @return ImmutableSet of genres of that book
   */
  public ImmutableSet<String> getGenres(Book book) {
    Set<String> genres = bookToGenres.get(book);
    if (genres == null) {
      return ImmutableSet.of();
    }
    return ImmutableSet.copyOf(genres);
  }

  /**
   * Takes in a set of genres and returns a set of Book objects
   * that have exactly the genres from the set.
   *
   * @param genres: Set of genres (as Strings)
   * @return ImmutableSet of books that have exactly these genres
   */
  public ImmutableSet<Book> getBooksWithExactGenres(Set<String> genres) {
    ImmutableSet.Builder<Book> matchingBooks = new ImmutableSet.Builder<Book>();
    for (Book book : bookToGenres.keySet()) {
      if (bookToGenres.get(book).equals(genres)) {
        matchingBooks.add(book);
      }
    }
    ImmutableSet<Book> matches = matchingBooks.build();
    if (matches.isEmpty()) {
      return ImmutableSet.of();
    }
    return matches;
  }
}

@@ -157,16 +157,323 @@
 t.Sets;%0A
+// import com.google.common.collect.ImmutableMultimap.Builder;%0Aimport com.google.common.collect.ImmutableMultimap;%0Aimport java. util. Collection;%0Aimport com.google.common.collect.ImmutableSetMultimap.Builder;%0Aimport com.google.common.collect.ImmutableSetMultimap;%0Aimport com.google.common.collect.Multimap;%0A
 import c
@@ -740,17 +740,34 @@
 private 
-M
+ImmutableSetMultim
 ap%3CBook,
@@ -767,28 +767,23 @@
 p%3CBook, 
-Set%3C
 String%3E
-%3E
  bookToG
@@ -799,17 +799,34 @@
 private 
-M
+ImmutableSetMultim
 ap%3CStrin
@@ -828,26 +828,21 @@
 String, 
-Set%3C
 Book%3E
-%3E
  genreTo
@@ -1114,61 +1114,127 @@
     
-bookToGenres = new HashMap
+ImmutableSetMultimap.Builder%3CBook, String%3E bookToGenresBuilder = new ImmutableSetMultimap.Builder
 %3CBook, 
-Set%3C
 String%3E
-%3E
 ();%0A    
 genr
@@ -1233,34 +1233,105 @@
     
-genreToBooks = new HashMap
+ImmutableSetMultimap.Builder%3CString, Book%3E genreToBooksBuilder = new ImmutableSetMultimap.Builder
 %3CStr
@@ -1339,18 +1339,13 @@
 ng, 
-Set%3C
 Book%3E
-%3E
 ();%0A
@@ -1380,36 +1380,34 @@
 %7B%0A      
-Set%3C
+for (
 String
-%3E
  genre
-s =
+:
  book.ge
@@ -1411,18 +1411,24 @@
 .genre()
-;%0A
+) %7B%0A    
       bo
@@ -1437,16 +1437,23 @@
 ToGenres
+Builder
 .put(boo
@@ -1456,25 +1456,24 @@
 (book, genre
-s
 );%0A      for
@@ -1473,228 +1473,159 @@
     
-for (String genre : genres) %7B%0A        if (genreToBooks.containsKey(genre)) %7B%0A
+    genreToBooksBuilder.put(genre, book);%0A  
     
+%7D%0A
     
-  genreToBooks.get(genre).add(book);%0A        %7D else %7B%0A          genreToBooks.put(genre, Sets.newHashSet(book));%0A        %7D%0A      %7D%0A    %7D
+%7D%0A    bookToGenres = bookToGenresBuilder.build();%0A    genreToBooks = genreToBooksBuilder.build();
 %0A  %7D
@@ -1853,16 +1853,25 @@
 ) %7B%0A    
+Immutable
 Set%3CStri
@@ -1986,35 +1986,14 @@
 urn 
-ImmutableSet.copyOf(
 genres
-)
 ;%0A  

use immutablesetmultimap