package com.example.musicapp.ViewModel

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.musicapp.Data.AlbumDetails
import com.example.musicapp.Data.Repository.DeezerRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class AlbumDetailsViewModel : ViewModel() {
    private val deezerRepository = DeezerRepository()

    private val _albumDetails = MutableStateFlow<AlbumDetails?>(null)
    val albumDetails: StateFlow<AlbumDetails?>
        get() = _albumDetails

    fun fetchAlbumDetails(albumId: Int) {
        viewModelScope.launch {
            try {
                val albumDetails = deezerRepository.getAlbumDetails(albumId)
                _albumDetails.value = albumDetails
            } catch (e: Exception) {
                Log.e("AlbumDetailsViewModel", "Failed to fetch album details: " + e.message)
            }
        }
    }
},package com.example.musicapp.ViewModel

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.musicapp.Data.Artist
import com.example.musicapp.Data.ArtistDetail
import com.example.musicapp.Data.Repository.DeezerRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class ArtistsViewModel : ViewModel() {
    private val deezerRepository = DeezerRepository()

    private val _artists = MutableStateFlow<List<Artist>>(emptyList())
    val artists: StateFlow<List<Artist>>
        get() = _artists

    private val _artistDetails = MutableStateFlow<List<ArtistDetail>>(emptyList())
    val artistDetails: StateFlow<List<ArtistDetail>>
        get() = _artistDetails

    fun fetchArtists(genreId: Int) {
        viewModelScope.launch {
            try {
                val artists = deezerRepository.getArtists(genreId)
                _artists.value = artists
            } catch (e: Exception) {
                Log.e("MusicViewModel", "Failed to fetch artists: " + e.message)
            }
        }
    }

    fun fetchArtistDetails(artistId: Int) {
        viewModelScope.launch {
            val artistDetailsData = deezerRepository.getArtistDetail(artistId)

            // Fetch artist’s albums
            val artistAlbums = deezerRepository.getArtistAlbums(artistId)

            // Combine artist details and albums
            val artistWithAlbums = artistDetailsData.copy(albums = artistAlbums)

            _artistDetails.value = listOf(artistWithAlbums)
        }
    }
},package com.example.musicapp.ViewModel

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.musicapp.Data.Category
import com.example.musicapp.Data.Repository.DeezerRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class CategoriesViewModel : ViewModel() {
    private val deezerRepository = DeezerRepository()
    private val _categories = MutableStateFlow<List<Category>>(emptyList())
    val categories: StateFlow<List<Category>>
        get() = _categories

    init {
        fetchCategories()
    }

    private fun fetchCategories() {
        viewModelScope.launch {
            try {
                val categories = deezerRepository.getCategories()
                _categories.value = categories
            } catch (e: Exception) {
                Log.e("CategoriesViewModel", "Failed to fetch categories: ${e.message}")
            }
        }
    }
},package com.example.musicapp.ViewModel

import android.content.Context
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.example.musicapp.Data.Song
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.gson.Gson
import com.google.android.exoplayer2.MediaItem
import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow


class PlayerViewModel(private val context: Context) : ViewModel() {
    var currentPlayer = mutableStateOf<SimpleExoPlayer?>(null)
    var currentSong = mutableStateOf<Song?>(null)
    var isPlaying = mutableStateOf(false)

    private val sharedPreferences = context.getSharedPreferences("music_app", Context.MODE_PRIVATE)
    private val gson = Gson()
    private val _favorites = MutableStateFlow<List<Song>>(emptyList())
    val favorites: StateFlow<List<Song>> = _favorites.asStateFlow()

    init {
        // Load favorites during ViewModel initialization
        _favorites.value = loadFavorites()
    }

    fun createExoPlayer(context: Context): SimpleExoPlayer {
        return SimpleExoPlayer.Builder(context).build()
    }

    fun playSong(context: Context, song: Song) {
        currentPlayer.value?.let {
            if (currentSong.value?.id == song.id) {
                if (isPlaying.value) {
                    pauseSong()
                } else {
                    resumeSong()
                }
                return
            } else {
                it.pause()
                it.release()
            }
        }

        currentSong.value = song
        val player = createExoPlayer(context)
        player.setMediaItem(MediaItem.fromUri(song.preview))
        player.prepare()
        player.play()
        isPlaying.value = true
        currentPlayer.value = player
    }

    fun pauseSong() {
        currentPlayer.value?.pause()
        isPlaying.value = false
    }

    fun resumeSong() {
        currentPlayer.value?.play()
        isPlaying.value = true
    }
    fun stopSong() {
        currentPlayer.value?.stop()
        isPlaying.value =false
    }

    override fun onCleared() {
        super.onCleared()
        currentPlayer.value?.release()
    }

    // Add a private function to load favorites from SharedPreferences
    private fun loadFavorites(): List<Song> {
        val json = sharedPreferences.getString("favorites", "[]") ?: "[]"
        val type = object : TypeToken<List<Song>>() {}.type
        return gson.fromJson(json, type)
    }

    // Save favorites to SharedPreferences
    private fun saveFavorites() {
        sharedPreferences.edit().putString("favorites", gson.toJson(_favorites.value)).apply()
    }
    // Update addFavoriteSong and removeFavoriteSong functions to save favorites after making changes
    fun addFavoriteSong(song: Song) {
        _favorites.value = _favorites.value.toMutableList().apply { add(song) }
        saveFavorites()
    }

    fun removeFavoriteSong(song: Song) {
        _favorites.value = _favorites.value.toMutableList().apply { remove(song) }
        saveFavorites()
    }

    fun isFavorite(song: Song): Boolean {
        return _favorites.value.contains(song)
    }

}-> these are my viewModel classes separated with "," . Can you explain every class in detail. I have to present my project soon. I want to be prepared. Also mention the technologies choosed in the class and explain why are they selected.