Newer
Older
bremer / src / main / kotlin / service / app / PlaylistAppService.kt
/*
 * Copyright (c) 2023. yo-saito. All Rights Reserved.
 */

package net.piedpiper.bremer.service.app

import net.piedpiper.bremer.entity.PlaylistAudioEntity
import net.piedpiper.bremer.entity.PlaylistEntity
import net.piedpiper.bremer.exception.BadRequestException
import net.piedpiper.bremer.exception.NotFoundException
import net.piedpiper.bremer.model.PlaylistAudioResponse
import net.piedpiper.bremer.model.PlaylistListResponse
import net.piedpiper.bremer.model.PlaylistRequest
import net.piedpiper.bremer.service.domain.AudioDomainService
import net.piedpiper.bremer.service.domain.PlaylistDomainService
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.UUID

@Service("bremer.service.PlaylistAppService")
class PlaylistAppService(
    @Qualifier("bremer.service.PlaylistDomainService")
    private val playlistDomainService: PlaylistDomainService,
    @Qualifier("bremer.service.AudioDomainService")
    private val audioDomainService: AudioDomainService
) {
    @Transactional
    fun getAllPlaylists(): PlaylistListResponse =
        PlaylistListResponse(playlistDomainService.findAll())

    @Transactional
    fun getPlaylist(slug: String): PlaylistAudioResponse =
        convertToPlaylistAudioResponse(
            playlistDomainService.findOneBySlug(slug) ?: throw NotFoundException()
        )

    @Transactional
    fun createPlaylist(request: PlaylistRequest): PlaylistAudioResponse =
        playlistDomainService.insertOne(
            convertToPlaylistEntity(request)
        ).let { entity ->
            val audioList = entity?.playlistAudio?.mapNotNull { it.audioId }
                ?.let {
                    audioDomainService.findAllByOrderedIds(it)
                } ?: emptyList()
            PlaylistAudioResponse(
                playlistEntity = entity,
                audioEntityList = audioList
            )
        }

    @Transactional
    fun updatePlaylist(slug: String, request: PlaylistRequest): PlaylistAudioResponse =
        playlistDomainService.findOneBySlug(slug)
            ?.let { playlist ->
                playlist.name = request.name
                val audioList = audioDomainService.findAllByOrderedSlugs(request.audioSlugs)
                if (request.audioSlugs.size != audioList.size) {
                    throw BadRequestException()
                }
                val playlistSize = playlist.playlistAudio?.size ?: 0
                playlist.playlistAudio = audioList.mapIndexed { idx, audio ->
                    PlaylistAudioEntity(
                        id = if (idx >= playlistSize) 0L else playlist?.playlistAudio!![idx].id,
                        playlistId = playlist.id,
                        sequence = idx,
                        audioId = audio.id
                    )
                }
                playlistDomainService.updateOne(
                    playlist
                ).let {
                    PlaylistAudioResponse(
                        playlistEntity = playlist,
                        audioEntityList = audioList
                    )
                }
            } ?: throw NotFoundException()

    private fun convertToPlaylistEntity(
        request: PlaylistRequest,
        id: Long = 0L,
        slug: String? = null
    ): PlaylistEntity =
        request.audioSlugs?.let {
            audioDomainService.findAllByOrderedSlugs(it)
        }?.associate { it.slug to it.id }
            .let { audioIdMap ->
                PlaylistEntity(
                    id = id,
                    slug = slug ?: UUID.randomUUID().toString(),
                    name = request.name,
                    playlistAudio = request.audioSlugs?.mapIndexed { idx, slug ->
                        PlaylistAudioEntity(
                            audioId = audioIdMap?.get(slug) ?: 0L,
                            sequence = idx
                        )
                    } ?: emptyList()
                )
            }

    private fun convertToPlaylistAudioResponse(entity: PlaylistEntity): PlaylistAudioResponse {
        val audioList = entity?.playlistAudio?.mapNotNull { it.audioId }
            ?.let {
                audioDomainService.findAllByOrderedIds(it)
            } ?: emptyList()
        return PlaylistAudioResponse(
            playlistEntity = entity,
            audioEntityList = audioList
        )
    }
}