# PregnancyStatusWidget.kt

    /*
     * The MIT License
     *
     * Original work sponsored and donated by The Danish Health Data Authority (http://www.sundhedsdatastyrelsen.dk)
     *
     * Copyright (C) 2021 The Danish Health Data Authority (http://www.sundhedsdatastyrelsen.dk)
     *
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy of
     * this software and associated documentation files (the "Software"), to deal in
     * the Software without restriction, including without limitation the rights to
     * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
     * of the Software, and to permit persons to whom the Software is furnished to do
     * so, subject to the following conditions:
     *
     *
     * The above copyright notice and this permission notice shall be included in all
     * copies or substantial portions of the Software.
     *
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     * SOFTWARE.
     */

    package dk.nsp.mingraviditet.ui.main.overview.widget

    import android.content.Context
    import android.util.AttributeSet
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.constraintlayout.widget.ConstraintLayout
    import androidx.viewbinding.ViewBinding
    import dk.nsp.mingraviditet.R
    import dk.nsp.mingraviditet.databinding.OverviewPregnancyControlDateBinding
    import dk.nsp.mingraviditet.databinding.OverviewPregnancyControlDefaultBinding
    import dk.nsp.mingraviditet.databinding.OverviewPregnancyControlDualBinding
    import dk.nsp.mingraviditet.databinding.OverviewPrengancyControlActionBinding
    import dk.nsp.mingraviditet.databinding.PregnancyStatusWidgetBinding
    import dk.nsp.mingraviditet.util.extensions.bindingadapters.setTextModel
    import dk.nsp.mingraviditet.util.extensions.toMediumFormat
    import dk.nsp.mingraviditet.util.extensions.toTextModelOrDefault
    import dk.nsp.shared.util.extensions.map
    import dk.nsp.util.TextModel

    class PregnancyStatusWidget @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : ConstraintLayout(context, attrs, defStyleAttr) {

        private var currentState: OverviewPregnancyState? = null

        private val binding =
            PregnancyStatusWidgetBinding.inflate(LayoutInflater.from(context), this, true)

        fun updateWith(state: OverviewPregnancyState) {
            currentState = state

            var shouldHideEmptyView = true

            when (state) {
                is OverviewPregnancyState.ActiveAndGaveBirth -> {
                    binding.pregnancyProgressSubtitle.setText(R.string.overview_your_pregnancy_active)

                    binding.fetusProgress.setup(
                        10.0,
                        state.numberOfFetuses
                    )
                }
                is OverviewPregnancyState.ActiveAndWaitingForBirth -> {
                    binding.pregnancyProgressSubtitle.setTextModel(
                        TextModel.from(
                            R.string.overview_your_pregnancy_due_date,
                            state.dueDate?.toMediumFormat().toTextModelOrDefault()
                        )
                    )

                    binding.fetusProgress.setup(
                        state.monthsIntoPregnancy,
                        state.numberOfFetuses
                    )
                }
                OverviewPregnancyState.None -> {
                    binding.pregnancyProgressSubtitle.setText(R.string.overview_your_pregnancy_not_available_description)

                    shouldHideEmptyView = false
                }
                is OverviewPregnancyState.PregnancyEnded -> {
                    //This view is hidden when pregnancy is ended
                }
            }

            setControls(state.widgetControls)

            binding.emptyView.visibility = shouldHideEmptyView.map(
                ifTrue = View.GONE,
                ifFalse = View.VISIBLE
            )
        }

        private fun setControls(widgetControls: List<OverviewWidgetControl>) {
            binding.controlsContainer.removeAllViews()

            val inflater = LayoutInflater.from(context)
            widgetControls.forEach { widgetControl ->
                when (widgetControl.type) {
                    is OverviewWidgetControlType.DateValue ->
                        inflateAndAddControlView(
                            inflater,
                            OverviewPregnancyControlDateBinding::inflate
                        ).also { binding ->
                            binding.valueText.setOnClickListener {
                                widgetControl.type.dateOfBirthCallback.invoke(
                                    widgetControl.type.date
                                )
                            }
                            val endDrawable =
                                if (widgetControl.type.date == null) R.drawable.ic_calendar else R.drawable.ic_edit
                            binding.valueText.setCompoundDrawablesWithIntrinsicBounds(
                                0,
                                0,
                                endDrawable,
                                0
                            )
                            binding.valueText.setTextModel(
                                widgetControl.type.date?.toMediumFormat().toTextModelOrDefault()
                            )
                            binding.descriptionText.setTextModel(widgetControl.title)
                        }
                    is OverviewWidgetControlType.DualValue ->
                        inflateAndAddControlView(
                            inflater,
                            OverviewPregnancyControlDualBinding::inflate
                        ).also { binding ->
                            binding.mainText.setTextModel(widgetControl.type.largeText)
                            binding.subText.setTextModel(widgetControl.type.smallText)
                            binding.descriptionText.setTextModel(widgetControl.title)
                        }
                    is OverviewWidgetControlType.TextAction ->
                        inflateAndAddControlView(
                            inflater,
                            OverviewPrengancyControlActionBinding::inflate
                        ).also { binding ->
                            binding.valueText.setOnClickListener { widgetControl.type.callback() }
                            binding.valueText.setTextModel(widgetControl.type.text)
                            binding.descriptionText.setTextModel(widgetControl.title)
                        }
                    is OverviewWidgetControlType.Value ->
                        inflateAndAddControlView(
                            inflater,
                            OverviewPregnancyControlDefaultBinding::inflate
                        ).also { binding ->
                            binding.valueText.setTextModel(widgetControl.type.text)
                            binding.descriptionText.setTextModel(widgetControl.title)
                        }
                }
            }
        }

        /**
         * Inflates the given [Binding] via [childInflater] adding it to the controller layout and returns the binding
         */
        private fun <Binding : ViewBinding> inflateAndAddControlView(
            inflater: LayoutInflater,
            childInflater: (inflater: LayoutInflater, parent: ViewGroup?, attachToParent: Boolean) -> Binding
        ): Binding = childInflater(inflater, binding.controlsContainer, true)

    }