<commit_before>package at.cpickl.gadsu.treatment.view

import at.cpickl.gadsu.client.Client
import at.cpickl.gadsu.development.debugColor
import at.cpickl.gadsu.service.minutes
import at.cpickl.gadsu.service.toMinutes
import at.cpickl.gadsu.treatment.NextTreatmentEvent
import at.cpickl.gadsu.treatment.PreviousTreatmentEvent
import at.cpickl.gadsu.treatment.Treatment
import at.cpickl.gadsu.treatment.TreatmentBackEvent
import at.cpickl.gadsu.treatment.TreatmentSaveEvent
import at.cpickl.gadsu.treatment.dyn.DynTreatment
import at.cpickl.gadsu.treatment.dyn.DynTreatmentTabbedPane
import at.cpickl.gadsu.view.Fields
import at.cpickl.gadsu.view.GadsuMenuBar
import at.cpickl.gadsu.view.MainContent
import at.cpickl.gadsu.view.MainContentType
import at.cpickl.gadsu.view.SwingFactory
import at.cpickl.gadsu.view.ViewNames
import at.cpickl.gadsu.view.addFormInput
import at.cpickl.gadsu.view.components.gadsuWidth
import at.cpickl.gadsu.view.components.newEventButton
import at.cpickl.gadsu.view.components.newPersistableEventButton
import at.cpickl.gadsu.view.components.panels.GridPanel
import at.cpickl.gadsu.view.components.panels.VFillFormPanel
import at.cpickl.gadsu.view.language.Labels
import at.cpickl.gadsu.view.logic.ModificationAware
import at.cpickl.gadsu.view.logic.ModificationChecker
import at.cpickl.gadsu.view.swing.Pad
import at.cpickl.gadsu.view.swing.enforceWidth
import at.cpickl.gadsu.view.swing.transparent
import at.cpickl.gadsu.view.swing.withFont
import com.google.common.collect.ComparisonChain
import com.google.common.eventbus.EventBus
import com.google.inject.assistedinject.Assisted
import org.slf4j.LoggerFactory
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import java.awt.Font
import java.awt.GridBagConstraints
import java.awt.Insets
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseListener
import javax.inject.Inject
import javax.swing.JLabel
import javax.swing.JMenuItem
import javax.swing.JPanel
import javax.swing.JPopupMenu
import javax.swing.JTextField
import javax.swing.SwingUtilities
import javax.swing.plaf.basic.BasicTabbedPaneUI

interface TreatmentView : ModificationAware, MainContent {
    fun readTreatment(): Treatment
    fun wasSaved(newTreatment: Treatment)
    fun enablePrev(enable: Boolean)
    fun enableNext(enable: Boolean)
    fun addDynTreatment(dynTreatment: DynTreatment)
    fun removeDynTreatmentAt(tabIndex: Int)
    fun getDynTreatmentAt(tabIndex: Int): DynTreatment
    fun getAllDynTreatmentClasses(): List<Class<DynTreatment>>
}


class SwingTreatmentView @Inject constructor(
        swing: SwingFactory,
        menuBar: GadsuMenuBar, // this is kind a design hack, but it was quicker to do ;)
        @Assisted private val client: Client,
        @Assisted private var treatment: Treatment
) : GridPanel(
        viewName = ViewNames.Treatment.MainPanel,
        _debugColor = Color.YELLOW
), TreatmentView {

    companion object {
        val DYN_TAB_TITLE_ADD = "+"
    }

    override val type = MainContentType.TREATMENT
    private val log = LoggerFactory.getLogger(javaClass)

    private val btnSave = swing.newPersistableEventButton(ViewNames.Treatment.SaveButton, { TreatmentSaveEvent() }).gadsuWidth()
    private val btnBack = swing.newEventButton(Labels.Buttons.Back, ViewNames.Treatment.BackButton, { TreatmentBackEvent() }).gadsuWidth()

    private val modificationChecker = ModificationChecker(this, btnSave, menuBar.treatmentSave)

    private val fields = Fields<Treatment>(modificationChecker)
    private val inpDateAndTime = fields.newDateAndTimePicker("Datum", treatment.date, { it.date }, ViewNames.Treatment.InputDatePrefix, JTextField.RIGHT)

    private val inpDuration = fields.newMinutesField("Dauer", { it.duration.toMinutes() }, ViewNames.Treatment.InputDuration, 2)
    private val inpAboutDiscomfort = fields.newTextArea("Zustand", { it.aboutDiscomfort }, ViewNames.Treatment.InputAboutDiscomfort)

    private val inpAboutContent = fields.newTextArea("Inhalt", { it.aboutContent }, ViewNames.Treatment.InputAboutContent)
    private val inpAboutDiagnosis = fields.newTextArea("Diagnose", { it.aboutDiagnosis }, ViewNames.Treatment.InputAboutDiagnosis)
    private val inpAboutFeedback = fields.newTextArea("Feedback", { it.aboutFeedback }, ViewNames.Treatment.InputAboutFeedback)
    private val inpAboutHomework = fields.newTextArea("Homework", { it.aboutHomework }, ViewNames.Treatment.InputAboutHomework)
    private val inpAboutUpcoming = fields.newTextArea("Upcoming", { it.aboutUpcoming }, ViewNames.Treatment.InputAboutUpcoming)
    private val inpNote = fields.newTextArea("Sonstige Anmerkungen", { it.note }, ViewNames.Treatment.InputNote)

    private val btnPrev = swing.newEventButton("<<", ViewNames.Treatment.ButtonPrevious, { PreviousTreatmentEvent() }).gadsuWidth()
    private val btnNext = swing.newEventButton(">>", ViewNames.Treatment.ButtonNext, { NextTreatmentEvent() }).gadsuWidth()

    private val subTreatmentView = DynTreatmentTabbedPane(treatment, swing.bus)
    private val bus: EventBus

    init {
        modificationChecker.enableChangeListener(subTreatmentView)
        bus = swing.bus
        if (treatment.yetPersisted) {
            modificationChecker.disableAll()
        }
        btnSave.changeLabel(treatment)
        fields.updateAll(treatment)

        initComponents()
        prepareSubTreatmentView()
    }

    override fun enablePrev(enable: Boolean) {
        btnPrev.isEnabled = enable
    }

    override fun enableNext(enable: Boolean) {
        btnNext.isEnabled = enable
    }

    override fun addDynTreatment(dynTreatment: DynTreatment) {
        subTreatmentView.addDynTreatment(dynTreatment)
    }

    override fun removeDynTreatmentAt(tabIndex: Int) {
        subTreatmentView.removeDynTreatmentAt(tabIndex)
    }

    override fun getDynTreatmentAt(tabIndex: Int) = subTreatmentView.getDynTreatmentAt(tabIndex)
    override fun getAllDynTreatmentClasses() = subTreatmentView.getAllDynTreatmentClasses()

    private fun initComponents() {
        c.fill = GridBagConstraints.NONE
        c.weightx = 0.0
        c.gridheight = 2
        c.anchor = GridBagConstraints.NORTH
        c.insets = Insets(Pad.DEFAULT_SIZE, 0, 0, Pad.DEFAULT_SIZE) // top right
        add(initClientProfile())

        c.gridx++
        c.gridheight = 1
        c.weightx = 1.0
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.NORTHWEST
        c.insets = Pad.bottom(20)
        add(JLabel("Behandlung #${treatment.number} für ${client.preferredName}").withFont(Font.BOLD, 20))

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.NORTHWEST
        c.weightx = 0.0
        c.weighty = 0.0
        c.insets = Pad.ZERO
        add(initDetailPanel())

        c.gridx = 0
        c.gridy++
        c.gridwidth = 2
        c.fill = GridBagConstraints.BOTH
        c.gridwidth = 2
        c.weightx = 1.0
        c.weighty = 1.0
        add(initMainPanel())

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.weighty = 0.0
        add(initButtonPanel())
    }

    private fun initMainPanel(): Component {
        val panel = GridPanel()
        with(panel.c) {
            fill = GridBagConstraints.BOTH
            weightx = 1.0
            weighty = 1.0
            panel.add(initTextAreas())

            gridx++
            weightx = 0.0
            insets = Pad.left(8)
            subTreatmentView.enforceWidth(400)
            panel.add(subTreatmentView)
        }
        return panel
    }

    private fun prepareSubTreatmentView() {
        subTreatmentView.addTab(DYN_TAB_TITLE_ADD, GridPanel().apply {
            c.anchor = GridBagConstraints.CENTER
            add(JLabel("Füge einen neuen Behandlungsteil hinzu."))
        })

        treatment.dynTreatments.forEach { addDynTreatment(it) }

        if (treatment.dynTreatments.isNotEmpty()) {
            subTreatmentView.selectedIndex = 1 // preselect first diagnosis tab
        }

//        val uiClass = subTreatmentView.ui.javaClass
        // AquaTabbedPaneContrastUI
        subTreatmentView.ui = object : BasicTabbedPaneUI() {
            override fun createMouseListener(): MouseListener {
                return object : MouseAdapter() {
                    override fun mousePressed(e: MouseEvent) {
                        val index = subTreatmentView.ui.tabForCoordinate(subTreatmentView, e.x, e.y)
                        if (index == -1) {<commit_msg>#57 including view (non functional integration)<commit_after>package at.cpickl.gadsu.treatment.view

import at.cpickl.gadsu.client.Client
import at.cpickl.gadsu.development.debugColor
import at.cpickl.gadsu.service.minutes
import at.cpickl.gadsu.service.toMinutes
import at.cpickl.gadsu.treatment.NextTreatmentEvent
import at.cpickl.gadsu.treatment.PreviousTreatmentEvent
import at.cpickl.gadsu.treatment.Treatment
import at.cpickl.gadsu.treatment.TreatmentBackEvent
import at.cpickl.gadsu.treatment.TreatmentSaveEvent
import at.cpickl.gadsu.treatment.dyn.DynTreatment
import at.cpickl.gadsu.treatment.dyn.DynTreatmentTabbedPane
import at.cpickl.gadsu.view.Fields
import at.cpickl.gadsu.view.GadsuMenuBar
import at.cpickl.gadsu.view.MainContent
import at.cpickl.gadsu.view.MainContentType
import at.cpickl.gadsu.view.SwingFactory
import at.cpickl.gadsu.view.ViewNames
import at.cpickl.gadsu.view.addFormInput
import at.cpickl.gadsu.view.components.gadsuWidth
import at.cpickl.gadsu.view.components.inputs.MeridianSelector
import at.cpickl.gadsu.view.components.newEventButton
import at.cpickl.gadsu.view.components.newPersistableEventButton
import at.cpickl.gadsu.view.components.panels.GridPanel
import at.cpickl.gadsu.view.components.panels.VFillFormPanel
import at.cpickl.gadsu.view.language.Labels
import at.cpickl.gadsu.view.logic.ModificationAware
import at.cpickl.gadsu.view.logic.ModificationChecker
import at.cpickl.gadsu.view.swing.Pad
import at.cpickl.gadsu.view.swing.enforceWidth
import at.cpickl.gadsu.view.swing.transparent
import at.cpickl.gadsu.view.swing.withFont
import com.google.common.collect.ComparisonChain
import com.google.common.eventbus.EventBus
import com.google.inject.assistedinject.Assisted
import org.slf4j.LoggerFactory
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Component
import java.awt.Font
import java.awt.GridBagConstraints
import java.awt.Insets
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import java.awt.event.MouseListener
import javax.inject.Inject
import javax.swing.JLabel
import javax.swing.JMenuItem
import javax.swing.JPanel
import javax.swing.JPopupMenu
import javax.swing.JTextField
import javax.swing.SwingUtilities
import javax.swing.plaf.basic.BasicTabbedPaneUI

interface TreatmentView : ModificationAware, MainContent {
    fun readTreatment(): Treatment
    fun wasSaved(newTreatment: Treatment)
    fun enablePrev(enable: Boolean)
    fun enableNext(enable: Boolean)
    fun addDynTreatment(dynTreatment: DynTreatment)
    fun removeDynTreatmentAt(tabIndex: Int)
    fun getDynTreatmentAt(tabIndex: Int): DynTreatment
    fun getAllDynTreatmentClasses(): List<Class<DynTreatment>>
}


class SwingTreatmentView @Inject constructor(
        swing: SwingFactory,
        menuBar: GadsuMenuBar, // this is kind a design hack, but it was quicker to do ;)
        @Assisted private val client: Client,
        @Assisted private var treatment: Treatment
) : GridPanel(
        viewName = ViewNames.Treatment.MainPanel,
        _debugColor = Color.YELLOW
), TreatmentView {

    companion object {
        val DYN_TAB_TITLE_ADD = "+"
    }

    override val type = MainContentType.TREATMENT
    private val log = LoggerFactory.getLogger(javaClass)

    private val btnSave = swing.newPersistableEventButton(ViewNames.Treatment.SaveButton, { TreatmentSaveEvent() }).gadsuWidth()
    private val btnBack = swing.newEventButton(Labels.Buttons.Back, ViewNames.Treatment.BackButton, { TreatmentBackEvent() }).gadsuWidth()

    private val modificationChecker = ModificationChecker(this, btnSave, menuBar.treatmentSave)

    private val fields = Fields<Treatment>(modificationChecker)
    private val inpDateAndTime = fields.newDateAndTimePicker("Datum", treatment.date, { it.date }, ViewNames.Treatment.InputDatePrefix, JTextField.RIGHT)

    private val inpDuration = fields.newMinutesField("Dauer", { it.duration.toMinutes() }, ViewNames.Treatment.InputDuration, 2)
    private val inpAboutDiscomfort = fields.newTextArea("Zustand", { it.aboutDiscomfort }, ViewNames.Treatment.InputAboutDiscomfort)

    private val inpAboutContent = fields.newTextArea("Inhalt", { it.aboutContent }, ViewNames.Treatment.InputAboutContent)
    private val inpAboutDiagnosis = fields.newTextArea("Diagnose", { it.aboutDiagnosis }, ViewNames.Treatment.InputAboutDiagnosis)
    private val inpAboutFeedback = fields.newTextArea("Feedback", { it.aboutFeedback }, ViewNames.Treatment.InputAboutFeedback)
    private val inpAboutHomework = fields.newTextArea("Homework", { it.aboutHomework }, ViewNames.Treatment.InputAboutHomework)
    private val inpAboutUpcoming = fields.newTextArea("Upcoming", { it.aboutUpcoming }, ViewNames.Treatment.InputAboutUpcoming)
    private val inpNote = fields.newTextArea("Sonstige Anmerkungen", { it.note }, ViewNames.Treatment.InputNote)

    // FIXME #57 check changes, init, etc...
    private val meridianSelector = MeridianSelector()

    private val btnPrev = swing.newEventButton("<<", ViewNames.Treatment.ButtonPrevious, { PreviousTreatmentEvent() }).gadsuWidth()
    private val btnNext = swing.newEventButton(">>", ViewNames.Treatment.ButtonNext, { NextTreatmentEvent() }).gadsuWidth()

    private val subTreatmentView = DynTreatmentTabbedPane(treatment, swing.bus)
    private val bus: EventBus

    init {
        modificationChecker.enableChangeListener(subTreatmentView)
        bus = swing.bus
        if (treatment.yetPersisted) {
            modificationChecker.disableAll()
        }
        btnSave.changeLabel(treatment)
        fields.updateAll(treatment)

        initComponents()
        prepareSubTreatmentView()
    }

    override fun enablePrev(enable: Boolean) {
        btnPrev.isEnabled = enable
    }

    override fun enableNext(enable: Boolean) {
        btnNext.isEnabled = enable
    }

    override fun addDynTreatment(dynTreatment: DynTreatment) {
        subTreatmentView.addDynTreatment(dynTreatment)
    }

    override fun removeDynTreatmentAt(tabIndex: Int) {
        subTreatmentView.removeDynTreatmentAt(tabIndex)
    }

    override fun getDynTreatmentAt(tabIndex: Int) = subTreatmentView.getDynTreatmentAt(tabIndex)
    override fun getAllDynTreatmentClasses() = subTreatmentView.getAllDynTreatmentClasses()

    private fun initComponents() {
        c.fill = GridBagConstraints.NONE
        c.weightx = 0.0
        c.gridheight = 2
        c.anchor = GridBagConstraints.NORTH
        c.insets = Insets(Pad.DEFAULT_SIZE, 0, 0, Pad.DEFAULT_SIZE) // top right
        add(initClientProfile())

        c.gridx++
        c.gridheight = 1
        c.weightx = 1.0
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.NORTHWEST
        c.insets = Pad.bottom(20)
        add(JLabel("Behandlung #${treatment.number} für ${client.preferredName}").withFont(Font.BOLD, 20))

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.anchor = GridBagConstraints.NORTHWEST
        c.weightx = 0.0
        c.weighty = 0.0
        c.insets = Pad.ZERO
        add(initDetailPanel())

        c.gridx = 0
        c.gridy++
        c.gridwidth = 2
        c.fill = GridBagConstraints.BOTH
        c.gridwidth = 2
        c.weightx = 1.0
        c.weighty = 1.0
        add(initMainPanel())

        c.gridy++
        c.fill = GridBagConstraints.HORIZONTAL
        c.weighty = 0.0
        add(initButtonPanel())
    }

    private fun initMainPanel(): Component {
        val panel = GridPanel()
        with(panel.c) {

            weightx = 0.0
            weighty = 0.0
            fill = GridBagConstraints.NONE
            meridianSelector.component.enforceWidth(100)
            panel.add(meridianSelector.component)

            // FIXME #57 move treatment view to top of panel, next to the detail panel containing picture and date text (right next to it)
            gridx++
            weightx = 1.0
            weighty = 1.0
            fill = GridBagConstraints.BOTH
            panel.add(initTextAreas())

            gridx++
            weightx = 0.0
            insets = Pad.left(8)
            subTreatmentView.enforceWidth(400)
            panel.add(subTreatmentView)
        }
        return panel
    }

    private fun prepareSubTreatmentView() {
        subTreatmentView.addTab(DYN_TAB_TITLE_ADD, GridPanel().apply {
            c.anchor = GridBagConstraints.CENTER
            add(JLabel("Füge einen neuen Behandlungsteil hinzu."))
        })

        treatment.dynTreatments.forEach { addDynTreatment(it) }

        if (treatment.dynTreatments.isNotEmpty()) {
            subTreatmentView.selectedIndex = 1 // preselect first diagnosis tab
        }

//        val uiClass = subTreatmentView.ui.javaClass
        // AquaTabbedPaneContrastUI
        subTreatmentView.ui = object : BasicTabbedPaneUI() {
            override fun createMouseListener(): MouseListener {
                return object : MouseAdapter() {
                    override fun mousePressed(e: MouseEvent) {
                        val index = subTreatmentView.ui.tabForCoordinate(subTreatmentView, e.x, e.y)
                        if (index == -1) {
{'fraction_non_alphanumeric': 0.09188517179023509, 'fraction_numerical': 0.005142405063291139, 'mean_word_length': 3.4077210460772105, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2491808', 'n_tokens_mistral': 5750, 'n_tokens_neox': 5261, 'n_words': 981}