# DocumentationViewModel.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.more.documentation

    import androidx.lifecycle.*
    import com.commonsense.android.kotlin.base.extensions.coroutines.launchIO
    import dagger.hilt.android.lifecycle.HiltViewModel
    import dk.nsp.domain.repository.DataCardRepository
    import dk.nsp.domain.repository.DocumentationRepository
    import dk.nsp.mingraviditet.R
    import dk.nsp.mingraviditet.ui.adapterviews.DetailsHeaderRow
    import dk.nsp.mingraviditet.ui.main.more.MoreSection
    import dk.nsp.mingraviditet.ui.widgets.HeaderViewWithIconBindingModel
    import dk.nsp.mingraviditet.util.android.recycler.RecyclerAdapterView
    import dk.nsp.mingraviditet.util.extensions.postSingleEvent
    import dk.nsp.mingraviditet.util.extensions.transform
    import dk.nsp.mingraviditet.util.livedata.SingleEvent
    import dk.nsp.shared.Failed
    import dk.nsp.shared.Success
    import dk.nsp.shared.util.sharedprefs.SharedPrefsHelper
    import dk.nsp.util.TextModel
    import javax.inject.Inject

    @HiltViewModel
    class DocumentationViewModel @Inject constructor(
        private val documentationRepository: DocumentationRepository,
        private val dataCardRepository: DataCardRepository,
        private val sharedPrefs: SharedPrefsHelper,
    ) : ViewModel() {

        private val _rowsToShow = MediatorLiveData<List<RecyclerAdapterView<*>>>().apply {
            addSource(dataCardRepository.currentDataCard) {
                postValue(generateRows(it?.episodeOfCareIdentifier))
            }
        }
        val rowsToShow: LiveData<List<RecyclerAdapterView<*>>> = _rowsToShow

        private val _onDocumentationSent = MutableLiveData<SingleEvent<Boolean>>()
        val onDocumentSent: LiveData<SingleEvent<Boolean>> = _onDocumentationSent

        private var isUploadingForEmployer = false

        private var isUploadingForPersonal = false

        private fun generateRows(episodeOfCareIdForDataCard: String?): List<RecyclerAdapterView<*>> {
            val enableEmpoyerDocumentationButton =
                episodeOfCareIdForDataCard != null && sharedPrefs.allowSendEmployerDocumentation(
                    episodeOfCareIdForDataCard
                )
            val enablePersonalDocumentationButton =
                episodeOfCareIdForDataCard != null && sharedPrefs.allowSendPersonalDocumentation(
                    episodeOfCareIdForDataCard
                )

            val headerModel = with(MoreSection.Documentation) {
                HeaderViewWithIconBindingModel(
                    getTitle(),
                    getDescription(),
                    getIcon()
                )
            }

            return listOf(
                DetailsHeaderRow(headerModel),
                DocumentationCardWithButtonRow(
                    DocumentationCardData(
                        TextModel.from(R.string.more_documentation_to_workplace_title),
                        TextModel.from(R.string.more_documentation_to_workplace_body),
                        TextModel.from(R.string.more_documentation_to_workplace_button_title),
                        isLoading = isUploadingForEmployer,
                        isButtonEnabled = enableEmpoyerDocumentationButton,
                        onClick = ::sendEmployerDocumentation
                    )
                ),
                DocumentationCardWithButtonRow(
                    DocumentationCardData(
                        TextModel.from(R.string.more_documentation_send_data_title),
                        TextModel.from(R.string.more_documentation_send_data_description),
                        TextModel.from(R.string.more_documentation_send_data_button),
                        isLoading = isUploadingForPersonal,
                        isButtonEnabled = enablePersonalDocumentationButton,
                        onClick = ::sendPersonalDocumentation
                    )
                ),
                DocumentationCardWithButtonRow(
                    DocumentationCardData(
                        TextModel.from(R.string.more_documentation_storage_period_title),
                        TextModel.from(R.string.more_documentation_storage_period_description)
                    )
                )
            )
        }

        private fun updateRows() {
            _rowsToShow.postValue(generateRows(dataCardRepository.currentDataCard.value?.episodeOfCareIdentifier))
        }

        private fun sendPersonalDocumentation() {
            viewModelScope.launchIO {
                val episodeOfCareId =
                    dataCardRepository.currentDataCard.value?.episodeOfCareIdentifier ?: return@launchIO

                isUploadingForPersonal = true
                updateRows()

                val result =
                    when (documentationRepository.getPersonalDocumentation(this, episodeOfCareId)
                        .await()) {
                        is Failed -> false

                        is Success -> {
                            sharedPrefs.setSentPersonalDocumentation(episodeOfCareId)
                            true
                        }
                    }
                _onDocumentationSent.postSingleEvent(result)
                isUploadingForPersonal = false
                updateRows()
            }
        }

        private fun sendEmployerDocumentation() {
            viewModelScope.launchIO {
                val episodeOfCareId =
                    dataCardRepository.currentDataCard.value?.episodeOfCareIdentifier ?: return@launchIO

                isUploadingForEmployer = true
                updateRows()

                val result =
                    when (documentationRepository.getEmployerDocumentation(this, episodeOfCareId)
                        .await()) {
                        is Failed -> false
                        is Success -> {
                            sharedPrefs.setSentEmployerDocumentation(episodeOfCareId)
                            true
                        }
                    }
                _onDocumentationSent.postSingleEvent(result)
                isUploadingForEmployer = false
                updateRows()
            }
        }
    }