package net.sergeych.toread

import net.sergeych.toread.fb2.Fb2Binary
import net.sergeych.toread.fb2.Fb2Book
import net.sergeych.toread.storage.BookReadingStatus

data class LibraryItem(
    val fileId: String,
    val bookId: String?,
    val title: String,
    val authors: List<String> = emptyList(),
    val language: String? = null,
    val date: String? = null,
    val format: String?,
    val sizeBytes: Long?,
    val storageUri: String?,
    val lastSeenAt: Long?,
    val readingStatus: BookReadingStatus = BookReadingStatus.NEW,
    val lastReadAt: Long? = null,
    val importedAt: Long? = null,
    val coverImage: ByteArray? = null,
    val coverImageMimeType: String? = null,
)

data class LibraryCover(
    val image: ByteArray,
    val mimeType: String?,
)

data class LibraryScanReport(
    val scannedFiles: Int,
    val importedFiles: Int,
    val skippedFiles: Int,
    val failedFiles: Int,
    val totalFiles: Int? = null,
)

data class LibraryScanProgress(
    val scannedFiles: Int,
    val importedFiles: Int,
    val skippedFiles: Int,
    val failedFiles: Int,
    val currentFile: String? = null,
    val totalFiles: Int? = null,
)

data class PlatformOpenBookRequest(
    val id: String,
    val displayName: String,
    val bytes: ByteArray,
)

data class ReadingPosition(
    val itemIndex: Int,
    val scrollOffset: Int,
)

data class BookInfoExtras(
    val bookmarks: List<BookmarkInfo> = emptyList(),
    val notes: List<NoteInfo> = emptyList(),
    val lastReadingPosition: ReadingPosition? = null,
)

data class BookmarkInfo(
    val title: String?,
    val selectedText: String?,
    val progress: Double?,
    val updatedAt: Long,
)

data class NoteInfo(
    val text: String,
    val progress: Double?,
    val updatedAt: Long,
)

enum class ThemeMode {
    LIGHT,
    DARK,
    SYSTEM,
}

expect fun defaultLibraryScanPath(): String?

expect suspend fun loadPlatformOpenBookRequest(): PlatformOpenBookRequest?

expect suspend fun chooseLibraryScanDirectory(): String?

expect suspend fun loadLibraryItems(): List<LibraryItem>

expect suspend fun loadLibraryItemsPage(limit: Int, offset: Int): List<LibraryItem>

expect suspend fun searchLibraryItems(query: String, limit: Int = 100): List<LibraryItem>

expect suspend fun loadLibraryItem(fileId: String): LibraryItem?

expect suspend fun loadLibraryItemCover(fileId: String): LibraryCover?

expect suspend fun scanLibrarySubtree(path: String, onProgress: (LibraryScanProgress) -> Unit): LibraryScanReport

expect suspend fun openLibraryBook(fileId: String): ByteArray?

expect suspend fun deleteLibraryItem(fileId: String): Boolean

expect suspend fun loadLibraryReadingPosition(fileId: String): ReadingPosition?

expect suspend fun saveLibraryReadingPosition(fileId: String, position: ReadingPosition)

expect suspend fun markLibraryReadingStatus(fileId: String, status: BookReadingStatus): Boolean

expect suspend fun loadBookInfoExtras(fileId: String): BookInfoExtras

expect suspend fun loadActiveReadingFileId(): String?

expect suspend fun saveActiveReadingFileId(fileId: String?)

expect suspend fun loadThemeMode(): ThemeMode

expect suspend fun saveThemeMode(mode: ThemeMode)

expect suspend fun loadScanDownloadsAutomatically(): Boolean

expect suspend fun saveScanDownloadsAutomatically(enabled: Boolean)

expect suspend fun loadDownloadsWasScanned(): Boolean

expect suspend fun saveDownloadsWasScanned(scanned: Boolean)

expect fun downloadsScanPath(): String?

expect fun isDownloadsScanPath(path: String): Boolean

expect fun isPlatformDarkTheme(): Boolean

expect fun watchPlatformDarkTheme(onChange: (Boolean) -> Unit): () -> Unit

expect fun libraryLogPath(): String?

expect fun formatLibraryLastReadTime(millis: Long): String

internal fun Fb2Book.libraryCoverBinary(): Fb2Binary? {
    val image = coverImages.firstOrNull() ?: bodyImages.firstOrNull()
    return image?.let(::binaryFor)
}
