//
//  PlayerUIView.swift
//  Demos
//

import Foundation
import SwiftUI
import AVFoundation

import PRESTOplay
import CastlabsApple
#if !os(tvOS)
import CastlabsChromecast
import CastlabsDownloader
#endif
import CastlabsSubtitles
import CastlabsThumbnails
import CastlabsYoubora
import NpawPlugin
import CastlabsBroadpeak
import CastlabsConviva
import CastlabsMux
import MuxCore

struct PlayerUIView: UIViewRepresentable {
    let demo: Demo
    let player: PlayerAPI

    @Binding var position: Double
    @Binding var thumbnailsVisible: Bool
    @Binding var thumbnail: UIImage

    func makeUIView(context: Context) -> UIView {
        return PlayerOwnerView(demo, player) {
            position = $0
        } thumbnailsCallback: {
            thumbnailsVisible = true
            thumbnail = $0
        }
    }

    func updateUIView(_ uiView: UIView, context: Context) { }
}

class PlayerOwnerView: UIView {
    let positionUpdate: (_ position: Double) -> Void
    let thumbnailUpdate: (_ thumbnail: UIImage) -> Void

    var player: PlayerAPI
    var subtitles: SubtitlesAPI?
    var thumbnails: ThumbnailsAPI?
    var analytics: AnalyticsAPI?

    override func layoutSubviews() {
        super.layoutSubviews()
        player.update(size: frame.size)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    init(_ demo: Demo, _ player: PlayerAPI,
         positionCallback: @escaping (Double) -> Void,
         thumbnailsCallback: @escaping (UIImage) -> Void) {
        self.player = player
        self.positionUpdate = positionCallback
        self.thumbnailUpdate = thumbnailsCallback
        super.init(frame: .zero)

        guard let url = demo.url else { return }
        guard let contentURL = URL(string: url) else { return }

        let config = PlayerConfiguration(with: contentURL)
        if let drm = demo.drmConfiguration {
            config.drmType = .drmToday
            config.drmSystem = .fairplay
            config.drmConfiguration = drm
        }
        self.player.load(config: config)

        self.player.onCurrentTime(rate: 0.2) { [weak self] position in
            guard let self else { return }
            self.positionUpdate(
                Double(position / self.player.duration) * 100.0)

            if let thumb = self.thumbnails?.getThumbnail(
                atTimestamp: CMTime(seconds: position, preferredTimescale: 1)) {

                if let image = UIImage.init(data: thumb.imageData) {
                    DispatchQueue.main.async { [weak self] in
                        self?.thumbnailUpdate(image)
                    }
                }
            }
        }

        self.player.onState = { [weak self] previous, state in
            guard let self else { return }

            if let error = self.player.error {
                print("Error \(error)")
            }

            if state == .ready {
                if let subtitlesUrl = demo.sideloadedSubtitle {
                    self.addSubtitles(subtitlesUrl)
                }
                if let thumbnailUrl = demo.sideloadedThumbnail {
                    self.addThumbnails(thumbnailUrl)
                }
                if true == demo.youboraEnabled {
                    self.addYoubora()
                }
                if true == demo.broadpeakEnabled {
                    self.addBroadpeak()
                }
                if true == demo.convivaEnabled {
                    self.addConviva(config)
                }
                if true == demo.muxEnabled {
                    self.addMux(config)     // Optional: Update custom metadata if needed.
                }
            }
        }

        player.attach(to: layer)
        player.open(autoplay: true)

        if let _ = demo.sideloadedSubtitle {
            subtitles = PRESTOplaySDK.shared.subtitles(for: player)
            subtitles?.subtitlesStyle = SubtitlesStyle(fromSystemSettings: true)
        }
        if let _ = demo.sideloadedThumbnail {
            thumbnails = PRESTOplaySDK.shared.thumbnails(for: player)
        }
        if true == demo.youboraEnabled {
            analytics = PRESTOplaySDK.shared.analytics(for: player, .youbora)
        }
        if true == demo.broadpeakEnabled {
            analytics = PRESTOplaySDK.shared.analytics(for: player, .broadpeak)
        }
        if true == demo.convivaEnabled {
            analytics = PRESTOplaySDK.shared.analytics(for: player, .conviva)
        }
        if true == demo.muxEnabled {
            analytics = PRESTOplaySDK.shared.analytics(for: player, .mux)
        }
    }

    func addSubtitles(_ subtitlesUrl: String) {
        guard let url = URL(string: subtitlesUrl) else {
            print("unable to parse subtitles url")
            return
        }

        let subtitlesTrack = TextTrack(
            id: UUID().uuidString,
            format: .web_vtt,
            isPlatformRendered: false,
            label: "sideloaded",
            language: "en",
            sourceUrl: url)

        subtitles?.addTextTrack(subtitlesTrack, completionHandler: { [weak self] track, error in
            if let error { print(error) } else { print("subtitles track loaded") }
            self?.player.setTextTrack(track)
        })
    }

    func addThumbnails(_ thumbnailUrl: String) {
        guard let url = URL(string: thumbnailUrl) else {
            print("unable to parse thumbnails url")
            return
        }

        thumbnails?.loadThumbnailsFrom(webVTTtrack: url, completionHandler: { error in
            if let error { print(error) } else { print("thumbnails loaded") }
        })
    }

    func addYoubora() {
        let youboraMetadata = YouboraMetadata(
            live: false,
            assetId: "assetId")
        youboraMetadata.analyticsOptions = NpawPlugin.AnalyticsOptions()
        youboraMetadata.analyticsOptions?.adCustomDimension1 = "test"
        youboraMetadata.analyticsOptions?.contentTitle = "test"
        youboraMetadata.analyticsOptions?.autoDetectBackground = false
        youboraMetadata.analyticsOptions?.userName = "User Name"
        youboraMetadata.accountCode = "ACCOUNT_CODE"
        analytics?.metadata = youboraMetadata
    }

    func addBroadpeak() {
        let broadpeakMetadata = AnalyticsMetadata(
            live: false,
            assetId: "broadkpeak_assetId")
        analytics?.metadata = broadpeakMetadata
    }

    func addConviva(_ config: PlayerConfiguration) {
        let convivaMetadata = ConvivaMetadata(
            live: false,
            assetId: "conviva_assetId")
        convivaMetadata.assetName = config.metaData?.title
        analytics?.metadata = convivaMetadata
    }

    func addMux(_ config: PlayerConfiguration) {
        guard let playerData = MUXSDKCustomerPlayerData(environmentKey: "YOUR-ENV-KEY")
        else { return }

        let videoData = MUXSDKCustomerVideoData()
        videoData.videoTitle = "Video Title"

        let customerData = MUXSDKCustomerData()
        customerData.customerPlayerData = playerData
        customerData.customerVideoData = videoData

        let muxMetadata = MuxMetadata(
            live: false,
            assetId: "assetId")
        muxMetadata.customerData = customerData
        analytics?.metadata = muxMetadata
    }
}
