package com.marvinelsen.willow.ui.cells

import com.marvinelsen.willow.ui.DictionaryEntryFx
import com.marvinelsen.willow.ui.util.createContextMenuForEntry
import javafx.geometry.VPos
import javafx.scene.control.Label
import javafx.scene.control.ListCell
import javafx.scene.control.ListView
import javafx.scene.layout.FlowPane
import javafx.scene.layout.VBox
import javafx.util.Callback

class DictionaryEntryCellFactory : Callback<ListView<DictionaryEntryFx?>, ListCell<DictionaryEntryFx?>> {
    override fun call(listView: ListView<DictionaryEntryFx?>): ListCell<DictionaryEntryFx?> {
        val entryCell = EntryCell()
        entryCell.prefWidthProperty().bind(listView.widthProperty().subtract(CELL_PADDING))
        return entryCell
    }

    companion object {
        private const val CELL_PADDING = 16
    }
}

internal class EntryCell : ListCell<DictionaryEntryFx?>() {
    private val labelHeadword = Label().apply {
        styleClass.add("list-view-entry")
    }

    private val labelDefinition = Label().apply {
        styleClass.add("list-view-definition")
    }

    private val labelPronunciation = Label().apply {
        styleClass.add("list-view-pronunciation")
    }

    private val flowPane = FlowPane(labelHeadword, labelPronunciation).apply {
        hgap = FLOW_PANE_HGAP
        rowValignment = VPos.BASELINE
    }

    private val root = VBox(flowPane, labelDefinition)

    init {
        text = null
        if (item != null) {
            contextMenu = createContextMenuForEntry(item!!)
        }
    }

    override fun updateItem(entry: DictionaryEntryFx?, empty: Boolean) {
        super.updateItem(entry, empty)
        if (empty || entry == null) {
            graphic = null
        } else {
            labelHeadword.text = entry.traditionalProperty.value
            labelPronunciation.text = entry.pinyinWithToneMarksProperty.value

            val definition = entry.definitions.joinToString(separator = " / ") { it.joinToString(separator = "; ") }
            labelDefinition.text = definition

            graphic = root
        }
    }

    companion object {
        private const val FLOW_PANE_HGAP = 8.0
    }
}
