AnimalRating/app/src/main/java/com/example/livingai/di/AppModule.kt

194 lines
8.2 KiB
Kotlin

package com.example.livingai.di
import android.content.Context
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import androidx.window.layout.WindowMetricsCalculator
import coil.ImageLoader
import coil.decode.SvgDecoder
import com.example.livingai.data.camera.DefaultCaptureHandler
import com.example.livingai.data.camera.DefaultMeasurementCalculator
import com.example.livingai.data.camera.DefaultOrientationChecker
import com.example.livingai.data.camera.DefaultTiltChecker
import com.example.livingai.data.camera.MockPoseAnalyzer
import com.example.livingai.data.camera.TFLiteObjectDetector
import com.example.livingai.data.local.CSVDataSource
import com.example.livingai.data.ml.AIModelImpl
import com.example.livingai.data.repository.AppDataRepositoryImpl
import com.example.livingai.data.repository.business.AnimalDetailsRepositoryImpl
import com.example.livingai.data.repository.business.AnimalProfileRepositoryImpl
import com.example.livingai.data.repository.business.AnimalRatingRepositoryImpl
import com.example.livingai.data.repository.media.CameraRepositoryImpl
import com.example.livingai.data.repository.media.VideoRepositoryImpl
import com.example.livingai.domain.camera.CaptureHandler
import com.example.livingai.domain.camera.MeasurementCalculator
import com.example.livingai.domain.camera.OrientationChecker
import com.example.livingai.domain.camera.PoseAnalyzer
import com.example.livingai.domain.camera.TiltChecker
import com.example.livingai.domain.ml.AIModel
import com.example.livingai.domain.ml.AnalyzerThresholds
import com.example.livingai.domain.ml.FeedbackAnalyzer
import com.example.livingai.domain.ml.FeedbackAnalyzerImpl
import com.example.livingai.domain.ml.ObjectDetector
import com.example.livingai.domain.ml.ObjectDetectorImpl
import com.example.livingai.domain.repository.AppDataRepository
import com.example.livingai.domain.repository.CameraRepository
import com.example.livingai.domain.repository.VideoRepository
import com.example.livingai.domain.repository.business.AnimalDetailsRepository
import com.example.livingai.domain.repository.business.AnimalProfileRepository
import com.example.livingai.domain.repository.business.AnimalRatingRepository
import com.example.livingai.domain.repository.business.DataSource
import com.example.livingai.domain.usecases.AppDataUseCases
import com.example.livingai.domain.usecases.DeleteAnimalProfile
import com.example.livingai.domain.usecases.GetAnimalDetails
import com.example.livingai.domain.usecases.GetAnimalProfiles
import com.example.livingai.domain.usecases.GetAnimalRatings
import com.example.livingai.domain.usecases.GetSettingsUseCase
import com.example.livingai.domain.usecases.ProfileEntry.ProfileEntryUseCase
import com.example.livingai.domain.usecases.ProfileListing.ProfileListingUseCase
import com.example.livingai.domain.usecases.ReadAppEntryUseCase
import com.example.livingai.domain.usecases.SaveAppEntryUseCase
import com.example.livingai.domain.usecases.SaveSettingsUseCase
import com.example.livingai.domain.usecases.SetAnimalDetails
import com.example.livingai.domain.usecases.SetAnimalRatings
import com.example.livingai.pages.addprofile.AddProfileViewModel
import com.example.livingai.pages.camera.CameraViewModel
import com.example.livingai.pages.camera.VideoViewModel
import com.example.livingai.pages.home.HomeViewModel
import com.example.livingai.pages.imagepreview.ImagePreviewViewModel
import com.example.livingai.pages.listings.ListingsViewModel
import com.example.livingai.pages.onboarding.OnBoardingViewModel
import com.example.livingai.pages.ratings.RatingViewModel
import com.example.livingai.pages.settings.SettingsViewModel
import com.example.livingai.pages.videopreview.VideoPreviewViewModel
import com.example.livingai.utils.Constants
import com.example.livingai.utils.CoroutineDispatchers
import com.example.livingai.utils.DefaultCoroutineDispatchers
import com.example.livingai.utils.ScreenDimensions
import com.example.livingai.utils.SilhouetteManager
import com.example.livingai.utils.TiltSensorManager
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = Constants.USER_SETTINGS)
val appModule = module {
single<DataStore<Preferences>> { androidContext().dataStore }
single<AppDataRepository> { AppDataRepositoryImpl(get()) }
single {
AppDataUseCases(
getSettings = GetSettingsUseCase(get()),
saveSettings = SaveSettingsUseCase(get()),
readAppEntry = ReadAppEntryUseCase(get()),
saveAppEntry = SaveAppEntryUseCase(get())
)
}
// Coroutine dispatchers (for testability)
single<CoroutineDispatchers> { DefaultCoroutineDispatchers() }
// Data Source
single<DataSource> {
CSVDataSource(
context = androidContext(),
fileName = Constants.ANIMAL_DATA_FILENAME,
dispatchers = get()
)
}
// Coil ImageLoader singleton
single {
ImageLoader.Builder(androidContext())
.components {
add(SvgDecoder.Factory())
}
.build()
}
factory<OrientationChecker> { DefaultOrientationChecker() }
factory<TiltChecker> { DefaultTiltChecker() }
factory<com.example.livingai.domain.camera.ObjectDetector> { TFLiteObjectDetector(androidContext()) }
factory<PoseAnalyzer> { MockPoseAnalyzer() }
// Handlers
factory<CaptureHandler> { DefaultCaptureHandler() }
factory<MeasurementCalculator> { DefaultMeasurementCalculator() }
// Initialize silhouettes once
single<ScreenDimensions>(createdAtStart = true) {
val ctx: Context = androidContext()
val metrics = WindowMetricsCalculator.getOrCreate()
.computeCurrentWindowMetrics(ctx)
val bounds = metrics.bounds
val screenWidth = bounds.width()
val screenHeight = bounds.height()
SilhouetteManager.initialize(ctx, screenWidth, screenHeight)
ScreenDimensions(screenWidth, screenHeight)
}
// ML Model
single<AIModel> { AIModelImpl(androidContext()) }
single<ObjectDetector> {
ObjectDetectorImpl(
context = androidContext(),
onResults = { _, _ -> }, // Callback will be set by ViewModel
onError = { error -> Log.e("ObjectDetector", "Error: $error") }
)
}
single<FeedbackAnalyzer> { FeedbackAnalyzerImpl(AnalyzerThresholds()) }
single { TiltSensorManager(androidContext()) }
// Repositories
single<AnimalProfileRepository> { AnimalProfileRepositoryImpl(get()) }
single<AnimalDetailsRepository> { AnimalDetailsRepositoryImpl(get()) }
single<AnimalRatingRepository> { AnimalRatingRepositoryImpl(get()) }
single<CameraRepository> { CameraRepositoryImpl(get(), get(), androidContext()) }
single<VideoRepository> { VideoRepositoryImpl(get()) }
// Use Cases
single { GetAnimalProfiles(get()) }
single { GetAnimalDetails(get()) }
single { GetAnimalRatings(get()) }
single { SetAnimalDetails(get()) }
single { SetAnimalRatings(get()) }
single { DeleteAnimalProfile(get()) }
//Use Cases
single {
ProfileEntryUseCase(
getAnimalDetails = GetAnimalDetails(get()),
setAnimalDetails = SetAnimalDetails(get())
)
}
single {
ProfileListingUseCase(
getAnimalProfiles = GetAnimalProfiles(get()),
deleteAnimalProfile = DeleteAnimalProfile(get())
)
}
// ViewModels
viewModel { HomeViewModel(get()) }
viewModel { OnBoardingViewModel(get()) }
viewModel { (savedStateHandle: androidx.lifecycle.SavedStateHandle?) ->
AddProfileViewModel(get(), get(), savedStateHandle)
}
viewModel { ListingsViewModel(get()) }
viewModel { SettingsViewModel(get()) }
viewModel { RatingViewModel(get(), get(), get(), get()) }
viewModel { CameraViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { VideoViewModel(get(), get(), get()) }
viewModel { ImagePreviewViewModel() }
viewModel { VideoPreviewViewModel() }
}