/*
* Copyright (C) 2023 MURENA SAS
* Copyright (C) 2021 E FOUNDATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package foundation.e.advancedprivacy
import android.app.Application
import android.content.Context
import android.os.Process
import androidx.lifecycle.DEFAULT_ARGS_KEY
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.CreationExtras
import foundation.e.advancedprivacy.common.WarningDialog
import foundation.e.advancedprivacy.data.repositories.AppListsRepository
import foundation.e.advancedprivacy.data.repositories.LocalStateRepository
import foundation.e.advancedprivacy.data.repositories.TrackersRepository
import foundation.e.advancedprivacy.domain.usecases.AppListUseCase
import foundation.e.advancedprivacy.domain.usecases.FakeLocationStateUseCase
import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase
import foundation.e.advancedprivacy.domain.usecases.IpScramblingStateUseCase
import foundation.e.advancedprivacy.domain.usecases.ShowFeaturesWarningUseCase
import foundation.e.advancedprivacy.domain.usecases.TrackersStateUseCase
import foundation.e.advancedprivacy.domain.usecases.TrackersStatisticsUseCase
import foundation.e.advancedprivacy.dummy.CityDataSource
import foundation.e.advancedprivacy.features.dashboard.DashboardViewModel
import foundation.e.advancedprivacy.features.internetprivacy.InternetPrivacyViewModel
import foundation.e.advancedprivacy.features.location.FakeLocationViewModel
import foundation.e.advancedprivacy.features.trackers.TrackersViewModel
import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersFragmentArgs
import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersViewModel
import foundation.e.privacymodules.fakelocation.FakeLocationModule
import foundation.e.privacymodules.ipscrambler.IIpScramblerModule
import foundation.e.privacymodules.ipscrambler.IpScramblerModule
import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
import foundation.e.privacymodules.permissions.data.ApplicationDescription
import foundation.e.privacymodules.permissions.data.ProfileType
import foundation.e.privacymodules.trackers.api.BlockTrackersPrivacyModule
import foundation.e.privacymodules.trackers.api.TrackTrackersPrivacyModule
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
/**
* Simple container to hold application wide dependencies.
*
*/
@OptIn(DelicateCoroutinesApi::class)
class DependencyContainer(val app: Application) {
val context: Context by lazy { app.applicationContext }
// Drivers
private val fakeLocationModule: FakeLocationModule by lazy { FakeLocationModule(app.applicationContext) }
private val permissionsModule by lazy { PermissionsPrivacyModule(app.applicationContext) }
private val ipScramblerModule: IIpScramblerModule by lazy { IpScramblerModule(app.applicationContext) }
private val appDesc by lazy {
ApplicationDescription(
packageName = context.packageName,
uid = Process.myUid(),
label = context.resources.getString(R.string.app_name),
icon = null,
profileId = -1,
profileType = ProfileType.MAIN
)
}
private val blockTrackersPrivacyModule by lazy { BlockTrackersPrivacyModule.getInstance(context) }
private val trackTrackersPrivacyModule by lazy { TrackTrackersPrivacyModule.getInstance(context) }
// Repositories
private val localStateRepository by lazy { LocalStateRepository(context) }
private val trackersRepository by lazy { TrackersRepository(context) }
private val appListsRepository by lazy { AppListsRepository(permissionsModule, context, GlobalScope) }
// Usecases
val getQuickPrivacyStateUseCase by lazy {
GetQuickPrivacyStateUseCase(localStateRepository)
}
private val ipScramblingStateUseCase by lazy {
IpScramblingStateUseCase(
ipScramblerModule, permissionsModule, appDesc, localStateRepository,
appListsRepository, GlobalScope
)
}
private val appListUseCase = AppListUseCase(appListsRepository)
val trackersStatisticsUseCase by lazy {
TrackersStatisticsUseCase(trackTrackersPrivacyModule, blockTrackersPrivacyModule, appListsRepository, context.resources)
}
val trackersStateUseCase by lazy {
TrackersStateUseCase(blockTrackersPrivacyModule, trackTrackersPrivacyModule, localStateRepository, trackersRepository, appListsRepository, GlobalScope)
}
private val fakeLocationStateUseCase by lazy {
FakeLocationStateUseCase(
fakeLocationModule, permissionsModule, localStateRepository, CityDataSource, appDesc, context, GlobalScope
)
}
val showFeaturesWarningUseCase by lazy {
ShowFeaturesWarningUseCase(localStateRepository = localStateRepository)
}
val viewModelsFactory by lazy {
ViewModelsFactory(
getQuickPrivacyStateUseCase = getQuickPrivacyStateUseCase,
trackersStatisticsUseCase = trackersStatisticsUseCase,
trackersStateUseCase = trackersStateUseCase,
fakeLocationStateUseCase = fakeLocationStateUseCase,
ipScramblerModule = ipScramblerModule,
ipScramblingStateUseCase = ipScramblingStateUseCase,
appListUseCase = appListUseCase
)
}
// Background
fun initBackgroundSingletons() {
trackersStateUseCase
ipScramblingStateUseCase
fakeLocationStateUseCase
UpdateTrackersWorker.periodicUpdate(context)
WarningDialog.startListening(
showFeaturesWarningUseCase,
GlobalScope,
context
)
Widget.startListening(
context,
getQuickPrivacyStateUseCase,
trackersStatisticsUseCase,
)
Notifications.startListening(
context,
getQuickPrivacyStateUseCase,
permissionsModule,
GlobalScope
)
}
}
@Suppress("LongParameterList")
class ViewModelsFactory(
private val getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase,
private val trackersStatisticsUseCase: TrackersStatisticsUseCase,
private val trackersStateUseCase: TrackersStateUseCase,
private val fakeLocationStateUseCase: FakeLocationStateUseCase,
private val ipScramblerModule: IIpScramblerModule,
private val ipScramblingStateUseCase: IpScramblingStateUseCase,
private val appListUseCase: AppListUseCase
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun create(modelClass: Class, extras: CreationExtras): T {
return when (modelClass) {
AppTrackersViewModel::class.java -> {
val app = extras[DEFAULT_ARGS_KEY]?.let {
appListUseCase.getApp(AppTrackersFragmentArgs.fromBundle(it).appUid)
} ?: appListUseCase.dummySystemApp
AppTrackersViewModel(
app = app,
trackersStateUseCase = trackersStateUseCase,
trackersStatisticsUseCase = trackersStatisticsUseCase,
getQuickPrivacyStateUseCase = getQuickPrivacyStateUseCase
)
}
TrackersViewModel::class.java ->
TrackersViewModel(
trackersStatisticsUseCase = trackersStatisticsUseCase
)
FakeLocationViewModel::class.java ->
FakeLocationViewModel(
fakeLocationStateUseCase = fakeLocationStateUseCase
)
InternetPrivacyViewModel::class.java ->
InternetPrivacyViewModel(
ipScramblerModule = ipScramblerModule,
getQuickPrivacyStateUseCase = getQuickPrivacyStateUseCase,
ipScramblingStateUseCase = ipScramblingStateUseCase,
appListUseCase = appListUseCase
)
DashboardViewModel::class.java ->
DashboardViewModel(
getPrivacyStateUseCase = getQuickPrivacyStateUseCase,
trackersStatisticsUseCase = trackersStatisticsUseCase
)
else -> throw IllegalArgumentException("Unknown class $modelClass")
} as T
}
}