package com.marvinelsen.willow

import com.marvinelsen.willow.domain.SearchMode
import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.services.FindCharacterService
import com.marvinelsen.willow.ui.services.FindWordsService
import com.marvinelsen.willow.ui.services.SearchService
import com.marvinelsen.willow.ui.util.ClipboardHelper
import javafx.beans.property.ObjectProperty
import javafx.beans.property.ReadOnlyBooleanProperty
import javafx.beans.property.ReadOnlyObjectProperty
import javafx.beans.property.SimpleObjectProperty
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.event.EventHandler

class Model(
    private val searchService: SearchService,
    private val findWordsService: FindWordsService,
    private val findCharacterService: FindCharacterService,
) {
    private val internalSelectedEntry: ObjectProperty<DictionaryEntryFx> = SimpleObjectProperty()
    private val internalSearchResults: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
    private val internalWordsContaining: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()
    private val internalCharacters: ObservableList<DictionaryEntryFx> = FXCollections.observableArrayList()

    val selectedEntry: ReadOnlyObjectProperty<DictionaryEntryFx> = internalSelectedEntry

    val searchResults: ObservableList<DictionaryEntryFx> =
        FXCollections.unmodifiableObservableList(internalSearchResults)
    val wordsContaining: ObservableList<DictionaryEntryFx> =
        FXCollections.unmodifiableObservableList(internalWordsContaining)
    val characters: ObservableList<DictionaryEntryFx> =
        FXCollections.unmodifiableObservableList(internalCharacters)

    val isSearching: ReadOnlyBooleanProperty = searchService.runningProperty()
    val isFindingWords: ReadOnlyBooleanProperty = findWordsService.runningProperty()
    val isFindingCharacters: ReadOnlyBooleanProperty = findCharacterService.runningProperty()

    init {
        searchService.onSucceeded = EventHandler {
            internalSearchResults.setAll(searchService.value)
        }
        findWordsService.onSucceeded = EventHandler {
            internalWordsContaining.setAll(findWordsService.value)
        }
        findCharacterService.onSucceeded = EventHandler {
            internalCharacters.setAll(findCharacterService.value)
        }
    }

    fun search(query: String, searchMode: SearchMode) {
        searchService.searchQuery = query
        searchService.searchMode = searchMode
        searchService.restart()
    }

    fun findWords() {
        findWordsService.entry = internalSelectedEntry.value
        findWordsService.restart()
    }

    fun findCharacters() {
        findCharacterService.entry = internalSelectedEntry.value
        findCharacterService.restart()
    }

    fun selectEntry(entry: DictionaryEntryFx) {
        internalWordsContaining.setAll(emptyList())
        internalCharacters.setAll(emptyList())
        internalSelectedEntry.value = entry
    }

    fun copyHeadwordOfSelectedEntry() {
        ClipboardHelper.copyString(internalSelectedEntry.value.traditionalProperty.value)
    }

    fun copyPronunciationOfSelectedEntry() {
        ClipboardHelper.copyString(internalSelectedEntry.value.pinyinWithToneMarksProperty.value)
    }
}
