import type { Storage } from "./Storage"; export interface ReadingLogEntry { book: string; pagesRead: number; pagesReadTotal: number; pagesRemaining: number; createdAt: Date; } export class ReadingLog { private entries: ReadingLogEntry[] = []; public constructor(private readonly storage: Storage) { this.load().catch((error) => { console.error("Failed to load reading log entries:", error); }); } async load(filename = "reading-log.json") { const entries = await this.storage.readJSON( filename ); if (entries) { this.entries = entries.map((entry) => ({ ...entry, createdAt: new Date(entry.createdAt), })); } } private sortEntries() { this.entries = this.entries.sort( (a, b) => a.createdAt.getTime() - b.createdAt.getTime() ); } async save(filename = "reading-log.json") { this.sortEntries(); await this.storage.writeJSON(filename, this.entries); } public getEntries(): ReadingLogEntry[] { return this.entries; } public getLatestEntry(book: string): ReadingLogEntry | null { const entriesForBook = this.entries.filter( (entry) => entry.book === book ); return entriesForBook.length > 0 ? entriesForBook[entriesForBook.length - 1] : null; } public async addEntry( book: string, pageEnded: number, pageCount: number ): Promise { const latestEntry = this.getLatestEntry(book); const newEntry: ReadingLogEntry = { book, pagesRead: latestEntry ? pageEnded - latestEntry.pagesReadTotal : pageEnded, pagesReadTotal: pageEnded, pagesRemaining: pageCount - pageEnded, createdAt: new Date(), }; await this.addRawEntry(newEntry); } public async addRawEntry(entry: ReadingLogEntry) { this.entries.push(entry); await this.save(); } public async removeEntries(book: string): Promise { this.entries = this.entries.filter((entry) => entry.book !== book); await this.save(); } public async removeLastEntry(book: string): Promise { const latestEntryIndex = this.entries.findLastIndex( (entry) => entry.book === book ); if (latestEntryIndex !== -1) { this.entries.splice(latestEntryIndex, 1); await this.save(); } } public async updateEntry(i: number, entry: ReadingLogEntry): Promise { this.entries[i] = entry; await this.save(); } public async spliceEntry(i: number): Promise { const entry = this.entries.splice(i, 1); await this.save(); return entry[0]; } public async clearEntries(): Promise { this.entries = []; await this.save(); } }