import APIClient
import ComposableArchitecture
import CoreMedia.CMTime
import Foundation
import Utilities

struct AlignedLyricsManager {
    @Shared(.inMemory(.alignedLyricsMap)) var alignedLyricsMap: AlignedLyricsMap = .defaultValue

    func updateMostRecentLyricsAndRemoveOld(_ clip: Clip) {
        $alignedLyricsMap.withLock {
            $0.updateMostRecentLyricsAndRemoveOld(clip.id)
        }
    }

    /*
        This just gives you the lyrics
        in the cache map for a given clip

        It does not trigger loading on clip for lyrics
     */
    func lyricsForClip(_ clip: Clip) -> Lyrics {
        return $alignedLyricsMap.withLock { $0.lyricsForClip(clip) }
    }

    /*
        This calls the endpoint for lyrics
     */
    func loadAlignedLyricsForClip(_ clip: Clip, givenTotalTime: CMTime) async {
        @Dependency(APIClient.self) var apiClient
        do {
            let lyrics = try await apiClient.getAlignedLyrics(clip)

            $alignedLyricsMap.withLock {
                $0.onLyricsResponseSuccess(lyrics, clip: clip, givenTotalTime: givenTotalTime)
            }
        } catch {
            $alignedLyricsMap.withLock {
                $0.onLyricsResponseFail(clip, givenTotalTime: givenTotalTime)
            }
        }
    }

    /*
        This is used on player on update time

        It updates the time value in the lyrics data object
        which updates which set of lyrics are shown

        It does not load new lyrics from endpoint
     */
    func updateLyricsTime(_ clip: Clip, time: TimeInterval?) {
        $alignedLyricsMap.withLock { $0.updateLyricTime(clip: clip, time) }
    }
}
