package suwayomi.tachidesk.manga.impl /* * Copyright (C) Contributors to the Suwayomi project * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import io.javalin.json.JsonMapper import io.javalin.json.fromJsonString import kotlinx.serialization.Serializable import suwayomi.tachidesk.manga.impl.MangaList.processEntries import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSourceOrStub import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass import uy.kohesive.injekt.injectLazy object Search { suspend fun sourceSearch( sourceId: Long, searchTerm: String, pageNum: Int, ): PagedMangaListDataClass { val source = getCatalogueSourceOrStub(sourceId) val searchManga = source.getSearchManga(pageNum, searchTerm, getFilterListOf(source)) return searchManga.processEntries(sourceId) } suspend fun sourceFilter( sourceId: Long, pageNum: Int, filter: FilterData, ): PagedMangaListDataClass { val source = getCatalogueSourceOrStub(sourceId) val filterList = if (filter.filter != null) buildFilterList(sourceId, filter.filter) else source.getFilterList() val searchManga = source.getSearchManga(pageNum, filter.searchTerm ?: "", filterList) return searchManga.processEntries(sourceId) } private val filterListCache = mutableMapOf() private fun getFilterListOf( source: CatalogueSource, reset: Boolean = false, ): FilterList { if (reset || !filterListCache.containsKey(source.id)) { filterListCache[source.id] = source.getFilterList() } return filterListCache[source.id]!! } fun getFilterList( sourceId: Long, reset: Boolean, ): List { val source = getCatalogueSourceOrStub(sourceId) return getFilterListOf(source, reset).list.map { FilterObject( when (it) { is Filter.Header -> "Header" is Filter.Separator -> "Separator" is Filter.Select<*> -> "Select" is Filter.Text -> "Text" is Filter.CheckBox -> "CheckBox" is Filter.TriState -> "TriState" is Filter.Group<*> -> "Group" is Filter.Sort -> "Sort" else -> throw RuntimeException("sealed class Cannot have more Subtypes!") }, when (it) { is Filter.Group<*> -> { SerializableGroup( it.name, it.state.map { item -> when (item) { is Filter.CheckBox -> FilterObject("CheckBox", item) is Filter.TriState -> FilterObject("TriState", item) is Filter.Text -> FilterObject("Text", item) is Filter.Select<*> -> FilterObject("Select", item) else -> throw RuntimeException("Illegal Group item type!") } }, ) } else -> { it } }, ) } } private fun Filter.Select<*>.getValuesType(): String = values::class.java.componentType!!.simpleName class SerializableGroup( name: String, state: List, ) : Filter>(name, state) data class FilterObject( val type: String, val filter: Filter<*>, ) fun setFilter( sourceId: Long, changes: List, ) { val source = getCatalogueSourceOrStub(sourceId) val filterList = getFilterListOf(source, false) updateFilterList(filterList, changes) } private fun updateFilterList( filterList: FilterList, changes: List, ): FilterList { changes.forEach { change -> when (val filter = filterList[change.position]) { is Filter.Header -> { // NOOP } is Filter.Separator -> { // NOOP } is Filter.Select<*> -> { filter.state = change.state.toInt() } is Filter.Text -> { filter.state = change.state } is Filter.CheckBox -> { filter.state = change.state.toBooleanStrict() } is Filter.TriState -> { filter.state = change.state.toInt() } is Filter.Group<*> -> { val groupChange = jsonMapper.fromJsonString(change.state) when (val groupFilter = filter.state[groupChange.position]) { is Filter.CheckBox -> groupFilter.state = groupChange.state.toBooleanStrict() is Filter.TriState -> groupFilter.state = groupChange.state.toInt() is Filter.Text -> groupFilter.state = groupChange.state is Filter.Select<*> -> groupFilter.state = groupChange.state.toInt() } } is Filter.Sort -> { filter.state = jsonMapper.fromJsonString(change.state, Filter.Sort.Selection::class.java) } } } return filterList } fun buildFilterList( sourceId: Long, changes: List, ): FilterList { val source = getCatalogueSourceOrStub(sourceId) val filterList = source.getFilterList() return updateFilterList(filterList, changes) } private val jsonMapper: JsonMapper by injectLazy() @Serializable data class FilterChange( val position: Int, val state: String, ) @Serializable data class FilterData( val searchTerm: String?, val filter: List?, ) @Suppress("UNUSED_PARAMETER") fun sourceGlobalSearch(searchTerm: String) { // TODO } }