// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.settings.feeds

import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import xyz.apiote.bimba.czwek.api.Error
import xyz.apiote.bimba.czwek.repo.FeedInfo
import xyz.apiote.bimba.czwek.repo.OfflineRepository
import xyz.apiote.bimba.czwek.repo.OnlineRepository
import xyz.apiote.bimba.czwek.repo.TrafficResponseException
import xyz.apiote.bimba.czwek.repo.join

class FeedsViewModel : ViewModel() {
	private val _settings = MutableLiveData<FeedsSettings>()
	val settings: LiveData<FeedsSettings> = _settings

	private val _feeds = MutableLiveData<Map<String, FeedInfo>>()
	val feeds: LiveData<Map<String, FeedInfo>> = _feeds

	private val _error = MutableLiveData<Error>()
	val error: LiveData<Error> = _error

	fun loadSettings(context: Context) {
		_settings.value = FeedsSettings.load(context)
	}

	fun setSettings(feedID: String, feedSettings: FeedSettings) {
		val feedsSettings = _settings.value ?: FeedsSettings(mutableMapOf())
		feedsSettings.settings[feedID] = feedSettings
		_settings.value = feedsSettings
	}

	fun setEnabled(feedID: String, enabled: Boolean) {
		val feedSettings = (_settings.value ?: FeedsSettings(mutableMapOf())).settings[feedID]
		setSettings(feedID, feedSettings?.copy(enabled = enabled) ?: FeedSettings(enabled, true))
	}

	fun loadFeeds(context: Context) {
		var offlineFeeds: Map<String, FeedInfo>? = null
		var onlineFeeds: Map<String, FeedInfo>? = null
		var error: Error? = null
		MainScope().launch {
			withContext(coroutineContext) {
				launch {
					val repository = OfflineRepository(context)
					offlineFeeds =
						repository.getFeeds(context)
					repository.close()
					if (!offlineFeeds.isNullOrEmpty()) {
						_feeds.value = offlineFeeds!!
					}
				}
				launch {
					try {
						val repository = OnlineRepository()
						onlineFeeds =
							repository.getFeeds(context)
					} catch (e: TrafficResponseException) {
						error = e.error
						Log.e("Feeds", "$e")
					}
				}
			}
			if (offlineFeeds.isNullOrEmpty() && error != null) {
				_error.value = error!!
			} else {
				joinFeeds(offlineFeeds, onlineFeeds).let { joinedFeeds ->
					_feeds.value = joinedFeeds
					val repository = OfflineRepository(context)
					repository.saveFeedCache(context, joinedFeeds)
					repository.close()
				}
			}
		}
	}

	private fun joinFeeds(
		feeds1: Map<String, FeedInfo>?,
		feeds2: Map<String, FeedInfo>?
	): Map<String, FeedInfo> {
		if (feeds1.isNullOrEmpty() && feeds2.isNullOrEmpty()) {
			return emptyMap()
		}

		if (feeds1.isNullOrEmpty()) {
			return feeds2!!
		}
		if (feeds2.isNullOrEmpty()) {
			return feeds1
		}

		return feeds1.keys.union(feeds2.keys).associateWith {
			feeds1[it].join(feeds2[it])
		}
	}
}
