import Foundation
import Siesta
import SwiftUI

extension PlayerModel {
    var isLoadingAvailableStreams: Bool {
        streamSelection.isNil || availableStreams.isEmpty
    }

    var isLoadingStream: Bool {
        !stream.isNil && stream != streamSelection
    }

    var availableStreamsSorted: [Stream] {
        availableStreams.sorted(by: streamsSorter)
    }

    func loadAvailableStreams(_ video: Video, onCompletion: @escaping (ResponseInfo) -> Void = { _ in }) {
        captions = nil
        availableStreams = []

        guard let playerInstance else { return }

        guard let api = playerAPI(video) else { return }
        logger.info("loading streams from \(playerInstance.description)")
        fetchStreams(api.video(video.videoID), instance: playerInstance, video: video, onCompletion: onCompletion)
    }

    private func fetchStreams(
        _ resource: Resource,
        instance: Instance,
        video: Video,
        onCompletion: @escaping (ResponseInfo) -> Void = { _ in }
    ) {
        resource
            .load()
            .onSuccess { response in
                if let video: Video = response.typedContent() {
                    VideosCacheModel.shared.storeVideo(video)
                    guard video.videoID == self.currentVideo?.videoID else {
                        self.logger.info("ignoring loaded streams from \(instance.description) as current video has changed")
                        return
                    }
                    self.availableStreams = self.streamsWithInstance(instance: instance, streams: video.streams)
                } else {
                    self.logger.critical("no streams available from \(instance.description)")
                }
            }
            .onCompletion(onCompletion)
            .onFailure { [weak self] responseError in
                self?.navigation.presentAlert(title: "Could not load streams", message: responseError.userMessage)
                self?.videoBeingOpened = nil
            }
    }

    func streamsWithInstance(instance: Instance, streams: [Stream]) -> [Stream] {
        streams.map { stream in
            stream.instance = instance

            if instance.app == .invidious, instance.proxiesVideos {
                if let audio = stream.audioAsset {
                    stream.audioAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: audio)
                }
                if let video = stream.videoAsset {
                    stream.videoAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: video)
                }
            }

            return stream
        }
    }

    func streamsSorter(_ lhs: Stream, _ rhs: Stream) -> Bool {
        if lhs.resolution.isNil || rhs.resolution.isNil {
            return lhs.kind < rhs.kind
        }

        return lhs.kind == rhs.kind ? (lhs.resolution.height > rhs.resolution.height) : (lhs.kind < rhs.kind)
    }
}
