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 by preferencesDataStore(name = Constants.USER_SETTINGS) val appModule = module { single> { androidContext().dataStore } single { AppDataRepositoryImpl(get()) } single { AppDataUseCases( getSettings = GetSettingsUseCase(get()), saveSettings = SaveSettingsUseCase(get()), readAppEntry = ReadAppEntryUseCase(get()), saveAppEntry = SaveAppEntryUseCase(get()) ) } // Coroutine dispatchers (for testability) single { DefaultCoroutineDispatchers() } // Data Source single { CSVDataSource( context = androidContext(), fileName = Constants.ANIMAL_DATA_FILENAME, dispatchers = get() ) } // Coil ImageLoader singleton single { ImageLoader.Builder(androidContext()) .components { add(SvgDecoder.Factory()) } .build() } factory { DefaultOrientationChecker() } factory { DefaultTiltChecker() } factory { TFLiteObjectDetector(androidContext()) } factory { MockPoseAnalyzer() } // Handlers factory { DefaultCaptureHandler() } factory { DefaultMeasurementCalculator() } // Initialize silhouettes once single(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 { AIModelImpl(androidContext()) } single { ObjectDetectorImpl( context = androidContext(), onResults = { _, _ -> }, // Callback will be set by ViewModel onError = { error -> Log.e("ObjectDetector", "Error: $error") } ) } single { FeedbackAnalyzerImpl(AnalyzerThresholds()) } single { TiltSensorManager(androidContext()) } // Repositories single { AnimalProfileRepositoryImpl(get()) } single { AnimalDetailsRepositoryImpl(get()) } single { AnimalRatingRepositoryImpl(get()) } single { CameraRepositoryImpl(get(), get(), androidContext()) } single { 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() } }