/***************************  Library.java  **************************/
import java.io.*;
import java.util.LinkedList;
class Author {
    String name;
    BookList books = new BookList();
    Author() {
    }
    public boolean equals(Object node) {
        return name.equals(((Author) node).name);
    }
    void display() {
        System.out.println(name);
        books.display();
    }
}
class Book {
    String title;
    Person person = null;
    Book() {
    }
    public boolean equals(Object node) {
        return title.equals(((Book) node).title);
    }
    public String toString() {
        return "    * " + title +
           (person != null ? " - checked out to " + person.name : "") + "\n";
    }
}
class CheckedOutBook {
    Author author = null;
    Book book = null;
    CheckedOutBook() {
    }
    public boolean equals(Object node) {
        return book.title.equals(((CheckedOutBook) node).book.title) &&
               author.name.equals(((CheckedOutBook) node).author.name);
    }
    public String toString() {
        return "    * " + author.name + ", " + book.title + "\n";
    }
}
class Person {
    String name;
    BookList books = new BookList();
    Person() {
    }
    public boolean equals(Object node) {
        return name.equals(((Person) node).name);
    }
    void display() {
        if (!books.isEmpty()) {
             System.out.println(name + " has the following books:");
             books.display();
        }
        else System.out.print(name + " has no books");
    }
}
class AuthorList extends LinkedList {
    AuthorList() {
        super();
    }
    void display() {
        Object[] authors = toArray();
        for (int i = 0; i < authors.length; i++)
            ((Author)authors[i]).display();
    }
}
class BookList extends LinkedList {
    BookList() {
        super();
    }
    void display() {
        for (int i = 0; i < size(); i++)
            System.out.print(get(i).toString());
    }
}
class PersonList extends LinkedList {
    PersonList() {
        super();
    }
    void display() {
        for (java.util.Iterator it = iterator(); it.hasNext(); )
             ((Person)it.next()).display();
    }
}
    
class Library {
    static AuthorList[] catalog = new AuthorList[(int)('Z'+1)];
    static PersonList[] people = new PersonList[(int)('Z'+1)];
    static String input;
    static InputStreamReader cin = new InputStreamReader(System.in);
    static BufferedReader buffer = new BufferedReader(cin);
    static String getString(String msg) {
        System.out.print(msg + " ");
        System.out.flush();
        try {
            input = buffer.readLine();
        } catch(IOException io) {
        }
        return input.substring(0,1).toUpperCase() + input.substring(1);
    }
    static void status() {
        System.out.println("Library has the following books:\n ");
        for (int i = (int) 'A'; i <= (int) 'Z'; i++)
            if (!catalog[i].isEmpty())
                catalog[i].display();
        System.out.println("\nThe following people are using the library:\n ");
        for (int i = (int) 'A'; i <= (int) 'Z'; i++)
            if (!people[i].isEmpty())
                people[i].display();
    }
    static void includeBook() {
        Author newAuthor = new Author();
        int oldAuthor;
        Book newBook = new Book();
        newAuthor.name = getString("Enter author's name:");
        newBook.title  = getString("Enter the title of the book:");
        oldAuthor = catalog[(int) newAuthor.name.charAt(0)].indexOf(newAuthor);
        if (oldAuthor == -1) {
             newAuthor.books.add(newBook);
             catalog[(int) newAuthor.name.charAt(0)].add(newAuthor);
        }
        else ((Author)catalog[(int) newAuthor.name.charAt(0)].get(oldAuthor)).
                books.add(newBook);
    }
    static void checkOutBook() {
        Person person = new Person(), personRef = new Person();
        Author author = new Author(), authorRef = new Author();
        Book   book   = new Book(), bookRef = new Book();
        int personIndex, bookIndex = -1, authorIndex = -1;
        CheckedOutBook bookToCheckOut = new CheckedOutBook();
        person.name = getString("Enter person's name:");
        while (authorIndex == -1) {
            author.name = getString("Enter author's name:");
            authorIndex = catalog[(int) author.name.charAt(0)].indexOf(author);
            if (authorIndex == -1)
                System.out.println("Misspelled author's name");
        }
        while (bookIndex == -1) {              
            book.title = getString("Enter the title of the book:");
            authorRef = (Author) catalog[(int) author.name.charAt(0)].get(authorIndex);
            bookIndex = authorRef.books.indexOf(book);
            if (bookIndex == -1)
                System.out.println("Misspelled title");
        }
        bookRef = (Book) authorRef.books.get(bookIndex);
        bookToCheckOut.author = authorRef;
        bookToCheckOut.book   = bookRef;
        personIndex = people[(int) person.name.charAt(0)].indexOf(person);
        if (personIndex == -1) {        // a new person in the library;
             person.books.add(bookToCheckOut);
             people[(int) person.name.charAt(0)].add(person);
             bookRef.person = (Person) people[(int) person.name.charAt(0)].getFirst();
        }
        else {
             personRef = (Person) people[(int) person.name.charAt(0)].get(personIndex);
             personRef.books.add(bookToCheckOut);
             bookRef.person = personRef;
        }
    }
    static void returnBook() {
        Person person = new Person();
        CheckedOutBook checkedOutBook = new CheckedOutBook();
        Book book = new Book();
        Author author = new Author(), authorRef = new Author();
        int personIndex = -1,  bookIndex = -1, authorIndex = -1;
        while (personIndex == -1) {
            person.name = getString("Enter person's name:");
            personIndex = people[(int) person.name.charAt(0)].indexOf(person);
            if (personIndex == -1)
                System.out.println("Person's name misspelled");
        }
        while (authorIndex == -1) {
            author.name = getString("Enter author's name:");
            authorIndex = catalog[(int) author.name.charAt(0)].indexOf(author);
            if (authorIndex == -1)
                System.out.println("Misspelled author's name");
        }
        while (bookIndex == -1) {
            book.title = getString("Enter the title of the book:");
            authorRef = (Author) catalog[(int) author.name.charAt(0)].get(authorIndex);
            bookIndex = authorRef.books.indexOf(book);
            if (bookIndex == -1)
                System.out.println("Misspelled title");
        }
        checkedOutBook.author = authorRef;
        checkedOutBook.book   = (Book) authorRef.books.get(bookIndex);
        ((Book)authorRef.books.get(bookIndex)).person = null;
        ((Person)people[(int) person.name.charAt(0)].get(personIndex)).
                books.remove(checkedOutBook);
    }
    static char menu() {
        return getString("\nEnter one of the following options:\n" +
              "1. Include a book in the catalog\n" +
              "2. Check out a book\n" +
              "3. Return a book\n4. Status\n5. Exit\n" +
              "Your option:").charAt(0);
    }
    public static void main(String args[]) {
        for (int i = 0; i <= (int) 'Z'; i++) {
            catalog[i] = new AuthorList();
            people[i] = new PersonList();
        }
        while (true)
            switch (menu()) {
                case '1': includeBook();  break;
                case '2': checkOutBook(); break;
                case '3': returnBook();   break;
                case '4': status();       break;
                case '5': return;
                default: System.out.println("Wrong option, try again.");
            }
    }
}