//
//  NativePlayerModule.swift
//  Pods
//
//

import AVKit
import CoreMedia
import Foundation
import PRESTOplay

// MARK: - PlayerModule

@available(tvOS 14.0, *)
@objc(RTCNativePlayerModuleSwift)
public class RTCNativePlayerModuleSwift: NSObject {
    
    /** Objective-C inteface object*/
    @objc public static let shared = RTCNativePlayerModuleSwift()
    
    // MARK: Lifecycle

    override init() {
        super.init()
        playerEventEmitter = PlayerEventEmitter(self)
        Self.playerModule.setEventEmitter(eventEmitter: playerEventEmitter)
        playerEventEmitter.startObserving()
    }

    // MARK: Internal

    /** Internal interface object */
    private static let playerModule = PlayerModule()
    private var playerEventEmitter: PlayerEventEmitter!
    private var eventEmitterFun: ((_ withName: String, _ body: Any?) -> Void)?
    
    /** Called by Objective-C module */
    @objc
    public func setEventEmitterFunc (
        emitter: @escaping (_ withName: String, _ body: Any?) -> Void
    ) {
        self.eventEmitterFun = emitter;
    }
    
    /** Called by playerEventEmitter */
    @objc
    public func sendEvent(
        withName: String,
        body: Any?
    ) {
        if let eventEmitterFun {
            eventEmitterFun(withName, body)
        }
    }


    @objc
    public func create(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.create(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func createApplePlayer(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.createApplePlayer(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func destroy(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.destroy(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func open(
        _ instanceId: String!,
        playerConfiguration jsonPlayerConfiguration: [String: Any],
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.open(instanceId,
            playerConfiguration: jsonPlayerConfiguration,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func play(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.play(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func replay(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.replay(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func pause(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.pause(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func stop(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.stop(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setPosition(
        _ instanceId: String!,
        newPositionMs: Int64,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setPosition(instanceId,
            newPositionMs: newPositionMs,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setPlaybackRate(
        _ instanceId: String!,
        newPlaybackRate: Double,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setPlaybackRate(instanceId,
            newPlaybackRate: newPlaybackRate,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setVolume(
        _ instanceId: String!,
        newVolume: Double,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setVolume(instanceId,
            newVolume: newVolume,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setMuted(
        _ instanceId: String!,
        newMuted: Bool,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setMuted(instanceId,
            newMuted: newMuted,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setAudioTrack(
        _ instanceId: String!,
        trackId: String,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setAudioTrack(instanceId,
            trackId: trackId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setVideoTrack(
        _ instanceId: String!,
        trackId: String,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setVideoTrack(instanceId,
            trackId: trackId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setVideoRendition(
        _ instanceId: String!,
        renditionId: String,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setVideoRendition(instanceId,
            renditionId: renditionId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func setTextTrack(
        _ instanceId: String!,
        trackId: String?,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.setTextTrack(instanceId,
            trackId: trackId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func enableAdaptiveVideo(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.enableAdaptiveVideo(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func supportsPictureInPicture(
        _ instanceId: String!,
        resolve: @escaping (Bool) -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.supportsPictureInPicture(instanceId,
            resolver: { result in resolve(result as! Bool)},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func isInPictureInPictureMode(
        _ instanceId: String!,
        resolve: @escaping (Bool) -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.isInPictureInPictureMode(instanceId,
            resolver: { result in resolve(result as! Bool)},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func enterPictureInPictureMode(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.enterPictureInPictureMode(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }

    @objc
    public func exitPictureInPictureMode(
        _ instanceId: String!,
        resolve: @escaping () -> Void,
        reject: @escaping (String?) -> Void
    ) {
        Self.playerModule.exitPictureInPictureMode(instanceId,
            resolver: { result in resolve()},
            rejecter: { code, message, error in reject(message)})
    }
}
