import Foundation

struct AudioPlayerCommand: CommandProcessor {

    static let commandType: CommandType = .audioPlayer

    let content: Content

    let results: PageGenerationResults

    let language: ContentLanguage

    init(content: Content, results: PageGenerationResults, language: ContentLanguage) {
        self.content = content
        self.results = results
        self.language = language
    }

    func process(_ arguments: [String], markdown: Substring) -> String {
        guard arguments.count == 2 else {
            invalid("Invalid audio player arguments")
            return ""
        }
        let fileId = arguments[0]
        let titleText = arguments[1]

        guard content.isValidIdForFile(fileId) else {
            invalid("Invalid file id \(fileId) for audio player")
            return ""
        }

        guard let file = content.file(fileId) else {
            results.missing(file: fileId, source: "Audio player song list")
            return ""
        }
        guard let data = file.dataContent() else {
            results.inaccessibleContent(file: file)
            return ""
        }
        let songs: [Song]
        do {
            songs = try JSONDecoder().decode([Song].self, from: data)
        } catch {
            results.invalidFormat(file: file, error: "Not valid JSON containing [Song]: \(error)")
            return ""
        }

        var playlist: [AudioPlayer.PlaylistItem] = []
        var amplitude: [AmplitudeSong] = []

        for song in songs {
            guard let image = content.file(song.cover) else {
                results.missing(file: song.cover, containedIn: file)
                continue
            }
            guard image.type.isImage else {
                results.warning("Cover '\(song.cover)' in file \(fileId) is not an image file")
                continue
            }

            guard let audioFile = content.file(song.file) else {
                results.missing(file: song.cover, containedIn: file)
                continue
            }
            guard audioFile.type.isAudio else {
                results.warning("Song '\(song.file)' in file \(fileId) is not an audio file")
                continue
            }

            let coverSize = 2 * content.settings.audioPlayer.playlistCoverImageSize
            let coverImage = image.imageVersion(width: coverSize, height: coverSize, type: image.type)
            let coverUrl = coverImage.outputPath

            results.require(image: coverImage)
            results.require(file: audioFile)

            let playlistItem = AudioPlayer.PlaylistItem(
                index: playlist.count,
                image: coverUrl,
                name: song.name,
                album: song.album,
                track: song.track,
                artist: song.artist)

            let amplitudeSong = AmplitudeSong(
                name: song.name,
                artist: song.artist,
                album: song.album,
                track: "\(song.track)",
                url: audioFile.absoluteUrl,
                cover_art_url: coverUrl)

            playlist.append(playlistItem)
            amplitude.append(amplitudeSong)
        }

        let footerScript = AudioPlayerScript(items: amplitude).content
        results.require(footer: footerScript)
        results.require(headers: .audioPlayerCss, .audioPlayerJs)

        results.require(icons:
            .audioPlayerClose,
            .audioPlayerPlaylist,
            .audioPlayerNext,
            .audioPlayerPrevious,
            .audioPlayerPlay,
            .audioPlayerPause
        )

        return AudioPlayer(
            playlistText: content.settings.audioPlayer.localized(in: language).playlistText,
            playingText: titleText,
            items: playlist).content
    }
}
