AndroidAPS/app/src/main/java/info/nightscout/androidaps/dialogs/InsulinDialog.kt
2019-12-27 19:20:38 +01:00

209 lines
11 KiB
Kotlin

package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.dialog_insulin.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import javax.inject.Inject
import kotlin.math.abs
import kotlin.math.max
class InsulinDialog : DialogFragmentWithDate() {
@Inject
lateinit var constraintChecker: ConstraintChecker
@Inject
lateinit var mainApp: MainApp
@Inject
lateinit var resourceHelper: ResourceHelper
@Inject
lateinit var profileFunction: ProfileFunction
companion object {
private const val PLUS1_DEFAULT = 0.5
private const val PLUS2_DEFAULT = 1.0
private const val PLUS3_DEFAULT = 2.0
}
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
validateInputs()
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
}
private fun validateInputs() {
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
overview_insulin_time.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.constraintapllied))
}
if (overview_insulin_amount.value > maxInsulin) {
overview_insulin_amount.value = 0.0
ToastUtils.showToastInUiThread(mainApp, resourceHelper.gs(R.string.bolusconstraintapplied))
}
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_insulin_time", overview_insulin_time.value)
savedInstanceState.putDouble("overview_insulin_amount", overview_insulin_amount.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_insulin, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time")
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount")
?: 0.0, 0.0, maxInsulin, ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
overview_insulin_plus05.text = toSignedString(SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
overview_insulin_plus05.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs()
}
overview_insulin_plus10.text = toSignedString(SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
overview_insulin_plus10.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs()
}
overview_insulin_plus20.text = toSignedString(SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
overview_insulin_plus20.setOnClickListener {
overview_insulin_amount.value = Math.max(0.0, overview_insulin_amount.value
+ SP.getDouble(resourceHelper.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs()
}
overview_insulin_time_layout.visibility = View.GONE
overview_insulin_record_only.setOnCheckedChangeListener { _, isChecked: Boolean ->
overview_insulin_time_layout.visibility = isChecked.toVisibility()
}
}
private fun toSignedString(value: Double): String {
val formatted = DecimalFormatter.toPumpSupportedBolus(value)
return if (value > 0) "+$formatted" else formatted
}
override fun submit(): Boolean {
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
?: return false
val insulin = SafeParse.stringToDouble(overview_insulin_amount.text)
val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value()
val actions: LinkedList<String?> = LinkedList()
val units = profileFunction.getUnits()
val unitLabel = if (units == Constants.MMOL) resourceHelper.gs(R.string.mmol) else resourceHelper.gs(R.string.mgdl)
val recordOnlyChecked = overview_insulin_record_only.isChecked
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
if (insulinAfterConstraints > 0) {
actions.add(resourceHelper.gs(R.string.bolus) + ": " + "<font color='" + resourceHelper.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + resourceHelper.gs(R.string.insulin_unit_shortname) + "</font>")
if (recordOnlyChecked)
actions.add("<font color='" + resourceHelper.gc(R.color.warning) + "'>" + resourceHelper.gs(R.string.bolusrecordedonly) + "</font>")
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(resourceHelper.gs(R.string.bolusconstraintappliedwarning, resourceHelper.gc(R.color.warning), insulin, insulinAfterConstraints))
}
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
if (eatingSoonChecked)
actions.add(resourceHelper.gs(R.string.temptargetshort) + ": " + "<font color='" + resourceHelper.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + resourceHelper.gs(R.string.unit_minute_short) + ")</font>")
val timeOffset = overview_insulin_time.value.toInt()
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
if (timeOffset != 0)
actions.add(resourceHelper.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
val notes = notes.text.toString()
if (notes.isNotEmpty())
actions.add(resourceHelper.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (insulinAfterConstraints > 0 || eatingSoonChecked) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (eatingSoonChecked) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(resourceHelper.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
.high(Profile.toMgdl(eatingSoonTT, profileFunction.getUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
}
if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes
if (recordOnlyChecked) {
detailedBolusInfo.date = time
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
} else {
detailedBolusInfo.date = DateUtil.now()
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(mainApp, ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", resourceHelper.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
mainApp.startActivity(i)
}
}
})
}
}
})
}
} else
activity?.let { activity ->
OKDialog.show(activity, resourceHelper.gs(R.string.bolus), resourceHelper.gs(R.string.no_action_selected))
}
return true
}
}