# Ui

## Overview

The `ui` module appears to provide the command-line entry point for the library management application. Its main responsibility is to present a text menu, collect user input, and delegate all business operations to the service layer rather than implementing domain logic itself. This keeps the module focused on interaction concerns: prompting, formatting output, and translating user choices into service calls.

At the center of the module is [`ConsoleUI`](ui/ConsoleUI.java:11), which wires together [`LibraryService`](service/LibraryService.java) and [`LoanService`](service/LoanService.java) and uses [`InputUtils`](util/InputUtils.java) for input handling.

## Key Classes and Interfaces

### [`ConsoleUI`](ui/ConsoleUI.java:11)

`ConsoleUI` is the only class in this module and serves as the interactive shell for the application. It owns the main menu loop, prompts the user for data, and prints results returned by the service layer. The class is intentionally thin: it does not create books, members, or loans directly, and it does not contain validation or persistence logic.

#### Responsibilities

- Run the interactive menu loop.
- Collect user input for each operation.
- Display success messages and simple empty-state messages.
- Delegate all real work to `LibraryService` and `LoanService`.

#### Constructor

- [`ConsoleUI.ConsoleUI(LibraryService libraryService, LoanService loanService)`](ui/ConsoleUI.java:15) accepts the two service dependencies and stores them in final fields.
- This is straightforward dependency injection and makes the UI easy to compose and test.

#### Methods

- [`start()`](ui/ConsoleUI.java:20) starts the application loop, prints the banner, shows the menu repeatedly, reads a numeric choice, dispatches to the appropriate handler, and closes input resources before exiting.
- [`printMenu()`](ui/ConsoleUI.java:42) prints the available commands. It has no side effects beyond console output.
- [`addBook()`](ui/ConsoleUI.java:56) prompts for title, author, and ISBN, then calls `libraryService.addBook(...)` and prints the returned value.
- [`listBooks()`](ui/ConsoleUI.java:63) fetches all books from `libraryService.listAllBooks()`, prints `No books.` when the list is empty, otherwise prints each book.
- [`searchBooks()`](ui/ConsoleUI.java:69) prompts for a keyword and prints each result from `libraryService.searchBooks(...)`.
- [`registerMember()`](ui/ConsoleUI.java:73) prompts for member name and email, calls `libraryService.registerMember(...)`, and prints the returned value.
- [`listMembers()`](ui/ConsoleUI.java:79) fetches members from `libraryService.listAllMembers()`, prints `No members.` when empty, otherwise prints each member.
- [`borrowBook()`](ui/ConsoleUI.java:85) prompts for a book ID and member ID, then prints the result of `loanService.borrowBook(...)`.
- [`returnBook()`](ui/ConsoleUI.java:92) prompts for a loan ID and prints the result of `loanService.returnBook(...)`.
- [`listLoans()`](ui/ConsoleUI.java:96) fetches active loans from `loanService.getActiveLoans()`, prints `No active loans.` when empty, otherwise prints each loan.

## How It Works

A typical session follows a simple request/response loop:

1. `start()` prints the application banner.
2. The UI repeatedly calls `printMenu()` and then reads a numeric choice using `InputUtils.readInt(...)`.
3. A `switch` statement dispatches to a private helper method for the selected action.
4. That helper gathers any additional user input with `InputUtils.readLine(...)`.
5. The helper delegates to the appropriate service method.
6. The result is printed directly to the console.
7. When the user chooses `0`, the loop exits, `Goodbye!` is printed, and `InputUtils.close()` is called.

This design keeps command handling centralized in one place while pushing all domain behavior into services. The UI therefore acts as a boundary layer between console input/output and the application core.

### Request flow example: borrowing a book

1. The user selects `6. Borrow book`.
2. [`start()`](ui/ConsoleUI.java:20) calls [`borrowBook()`](ui/ConsoleUI.java:85).
3. `borrowBook()` prompts for a book ID and member ID.
4. It passes those values to `loanService.borrowBook(...)`.
5. Whatever message or representation the service returns is printed to the console.

The same pattern is used for returning books and registering members: the UI captures input, the service performs the operation, and the UI prints the outcome.

## Data Model

The `ui` module does not define its own data model, but it works with three domain types returned by the service layer:

- [`Book`](model/Book.java:Book) for book listings and search results.
- [`Member`](model/Member.java:Member) for member listings.
- [`Loan`](model/Loan.java:Loan) for active loan listings.

`ConsoleUI` treats these objects as printable values and relies on their `toString()` implementations when it calls `System.out::println`. That means the readability of console output depends heavily on how those model classes format themselves.

## Dependencies and Integration

`ConsoleUI` depends on a small set of application-layer types:

- [`LibraryService`](service/LibraryService.java) for book and member operations.
- [`LoanService`](service/LoanService.java) for borrowing, returning, and listing loans.
- [`InputUtils`](util/InputUtils.java) for reading user input and closing shared input resources.
- [`Book`](model/Book.java:Book), [`Member`](model/Member.java:Member), and [`Loan`](model/Loan.java:Loan) for displaying returned entities.

```mermaid
flowchart TD
UiModule["Ui module"] --> ConsoleUI["ConsoleUI"]
ConsoleUI --> LibraryService["LibraryService"]
ConsoleUI --> LoanService["LoanService"]
ConsoleUI --> InputUtils["InputUtils"]
ConsoleUI --> Book["Book"]
ConsoleUI --> Member["Member"]
ConsoleUI --> Loan["Loan"]
```

The module has no child packages and no detected cross-module relationships beyond these service and model dependencies.

## Notes for Developers

- `ConsoleUI` is intentionally procedural. If you add new functionality, the expected pattern is to add a new menu option, create a small private handler method, and delegate to a service.
- The class assumes service methods return printable results. If a service changes its return type or message format, the console output will change accordingly.
- `start()` always closes `InputUtils` before exiting. If you reuse the input utility elsewhere, be mindful of that shared lifecycle.
- Empty lists are handled with explicit messages such as `No books.`, `No members.`, and `No active loans.`. Keep this convention in mind if you add new list-oriented commands.
- The menu is hard-coded in `printMenu()`. Adding or reordering options requires updating both the menu text and the `switch` dispatch in `start()`.
- The UI currently uses simple `System.out.println` output and does not perform validation beyond choice selection. Any stricter validation likely belongs in the service or utility layers.
