//
//  PlayerController.swift
//  LiveApple
//
//  Created by Shadowfacts on 9/24/22.
//

import Foundation
import AVKit
import ActivityKit
import AudioToolbox
import MediaPlayer

@MainActor
class PlayerController: ObservableObject {
    private let reader: AVAssetReader
    private let readQueue = DispatchQueue(label: "PlayerController reading", qos: .userInitiated)
    private let asset: AVAsset
    let player: AVPlayer
    @Published private(set) var frames: [(CMTime, Frame)] = []
    private var lastPlayedFrameIndex = 0
    @Published var currentFrame: Frame?
    var activity: Activity<BadAppleAttributes>?
    private var timer: Timer?
    var initializedNowPlaying = false
    
    init() {
        let url = Bundle.main.url(forResource: "badapple", withExtension: "mp4")!
        asset = AVURLAsset(url: url)
        
        player = AVPlayer(playerItem: AVPlayerItem(asset: asset))
        reader = try! AVAssetReader(asset: asset)
        
        player.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 30), queue: .main) { [weak self] time in
            self?.emitFrame(for: time)
        }
    }
    
    func start() async {
        let track = try! await asset.loadTracks(withMediaType: .video).first!
        let trackOutput = AVAssetReaderTrackOutput(track: track, outputSettings: [
            kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),
        ])
        reader.add(trackOutput)
        
        let date = Date()
        print("start reading")
        let frames = await withCheckedContinuation { continuation in
            self.readQueue.async {
                guard self.reader.startReading() else {
                    fatalError()
                }
                var frames: [(CMTime, Frame)] = []
                while let buffer = trackOutput.copyNextSampleBuffer() {
                    frames.append((buffer.presentationTimeStamp, Frame(pixelBuffer: buffer.imageBuffer!)))
                }
                continuation.resume(returning: frames)
            }
        }
        print("done reading after: \(-date.timeIntervalSinceNow)")
        self.frames = frames
        
        // using the AVPlayer gives you sound
//        self.player.play()
        
        // doing it manually lets you update while in the background
        let start = Date()
        timer = .scheduledTimer(withTimeInterval: 1/30, repeats: true, block: { [unowned self] _ in
            let diff = -start.timeIntervalSinceNow
            let cmTime = CMTime(value: CMTimeValue(diff * 1000), timescale: 1000)
            Task {
                await self.emitFrame(for: cmTime)
            }
        })
    }
    
    func stop() {
        reader.cancelReading()
    }
    
    func emitFrame(for time: CMTime) {
        if let index = frames[lastPlayedFrameIndex...].firstIndex(where: { $0.0 >= time }) {
            lastPlayedFrameIndex = index
            let (time, frame) = frames[index]
//            print("playing frame at \(time)")
            currentFrame = frame
            
//            if !initializedNowPlaying {
//                initializedNowPlaying = true
//                let artwork = MPMediaItemArtwork(boundsSize: CGSize(width: 60, height: 45)) { _ in
//                    UIImage(cgImage: frame.createImage())
//                }
//                let center = MPNowPlayingInfoCenter.default()
//                let duration = Double(asset.duration.value) / Double(asset.duration.timescale)
//                center.nowPlayingInfo = [
//                    MPMediaItemPropertyTitle: "Bad Apple!",
//                    MPMediaItemPropertyArtist: "ZUN",
//                    MPMediaItemPropertyAlbumArtist: "ZUN",
//                    MPMediaItemPropertyAlbumTitle: "asdf",
//                    MPMediaItemPropertyArtwork: artwork,
//                    MPMediaItemPropertyPlaybackDuration: duration as NSNumber,
//                    MPNowPlayingInfoPropertyMediaType: MPMediaType.music.rawValue,
//                    MPNowPlayingInfoPropertyAssetURL: Bundle.main.url(forResource: "badapple", withExtension: "mp4")!,
//                    MPNowPlayingInfoPropertyIsLiveStream: false,
//                    MPNowPlayingInfoPropertyPlaybackRate: 1.0,
//                    MPNowPlayingInfoPropertyDefaultPlaybackRate: 1.0,
//                ]
//            }
//
//
//            let artwork = MPMediaItemArtwork(boundsSize: CGSize(width: 60, height: 45)) { size in
//                UIImage(cgImage: frame.createImage())
//            }
//            var info = MPNowPlayingInfoCenter.default().nowPlayingInfo!
//            info[MPMediaItemPropertyArtwork] = artwork
//            info[MPMediaItemPropertyTitle] = index.description
//            MPNowPlayingInfoCenter.default().nowPlayingInfo = info
        } else {
            print("no frame")
        }
    }
    
}
