import Foundation
import UIKit
import Display
import BatchVideoRendering
import AccountContext
import TelegramCore
import AVFoundation
import SwiftSignalKit
import PhotoResources

open class GifVideoLayer: AVSampleBufferDisplayLayer, BatchVideoRenderingContext.Target {
    private let context: AccountContext
    private let batchVideoContext: BatchVideoRenderingContext
    private let userLocation: MediaResourceUserLocation
    private let file: FileMediaReference?
    
    private var batchVideoTargetHandle: BatchVideoRenderingContext.TargetHandle?
    public var batchVideoRenderingTargetState: BatchVideoRenderingContext.TargetState?
    
    private var thumbnailDisposable: Disposable?
    
    private var isReadyToRender: Bool = false
    
    public var started: (() -> Void)?
    
    public var shouldBeAnimating: Bool = false {
        didSet {
            if self.shouldBeAnimating == oldValue {
                return
            }
            self.updateShouldBeRendering()
        }
    }
    
    public init(context: AccountContext, batchVideoContext: BatchVideoRenderingContext, userLocation: MediaResourceUserLocation, file: FileMediaReference?, synchronousLoad: Bool) {
        self.context = context
        self.batchVideoContext = batchVideoContext
        self.userLocation = userLocation
        self.file = file
        
        super.init()
        
        self.videoGravity = .resizeAspectFill
        
        if let file = self.file {
            if let dimensions = file.media.dimensions {
                self.thumbnailDisposable = (mediaGridMessageVideo(postbox: context.account.postbox, userLocation: userLocation, videoReference: file, synchronousLoad: synchronousLoad, nilForEmptyResult: true)
                |> deliverOnMainQueue).start(next: { [weak self] transform in
                    guard let strongSelf = self else {
                        return
                    }
                    let boundingSize = CGSize(width: 93.0, height: 93.0)
                    let imageSize = dimensions.cgSize.aspectFilled(boundingSize)
                    
                    if let image = transform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() {
                        Queue.mainQueue().async {
                            if let strongSelf = self {
                                strongSelf.contents = image.cgImage
                                strongSelf.setupVideo()
                                strongSelf.started?()
                            }
                        }
                    } else {
                        strongSelf.setupVideo()
                    }
                })
            } else {
                self.setupVideo()
            }
        }
    }
    
    override public init(layer: Any) {
        guard let layer = layer as? GifVideoLayer else {
            preconditionFailure()
        }
        
        self.context = layer.context
        self.batchVideoContext = layer.batchVideoContext
        self.userLocation = layer.userLocation
        self.file = layer.file
        
        super.init(layer: layer)
    }
    
    required public init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    deinit {
        self.thumbnailDisposable?.dispose()
    }
    
    private func setupVideo() {
        self.isReadyToRender = true
        self.updateShouldBeRendering()
    }
    
    private func updateShouldBeRendering() {
        let shouldBeRendering = self.shouldBeAnimating && self.isReadyToRender
        
        if shouldBeRendering, let file = self.file {
            if self.batchVideoTargetHandle == nil {
                self.batchVideoTargetHandle = self.batchVideoContext.add(target: self, file: file, userLocation: self.userLocation)
            }
        } else {
            self.batchVideoTargetHandle = nil
        }
    }
    
    public func setSampleBuffer(sampleBuffer: CMSampleBuffer) {
        if #available(iOS 17.0, *) {
            self.sampleBufferRenderer.enqueue(sampleBuffer)
        } else {
            self.enqueue(sampleBuffer)
        }
    }
}