import Foundation
import UIKit
import AnimationCache
import Display
import RLottieBinding
import GZip
import WebPBinding

public func cacheLottieAnimation(data: Data, width: Int, height: Int, keyframeOnly: Bool, writer: AnimationCacheItemWriter, firstFrameOnly: Bool, customColor: UIColor?) {
    let work: () -> Void = {
        let decompressedData = TGGUnzipData(data, 2 * 1024 * 1024) ?? data
        guard let animation = LottieInstance(data: decompressedData, fitzModifier: .none, colorReplacements: nil, cacheKey: "") else {
            writer.finish()
            return
        }
        
        let frameSkip: Int = 2
        /*if animation.frameRate >= 60 {
            if ProcessInfo.processInfo.processorCount > 2 {
                frameSkip = 1
            } else {
                frameSkip = 2
            }
        } else {
            frameSkip = 1
        }*/
        
        let frameDuration = Double(frameSkip) / Double(animation.frameRate)
        for i in stride(from: 0, through: animation.frameCount - 1, by: frameSkip) {
            if writer.isCancelled {
                break
            }
            writer.add(with: { surface in
                animation.renderFrame(with: i, into: surface.argb, width: Int32(surface.width), height: Int32(surface.height), bytesPerRow: Int32(surface.bytesPerRow))
                if customColor != nil {
                    for y in 0 ..< surface.height {
                        for x in 0 ..< surface.width {
                            let pixel = surface.argb.advanced(by: y * surface.bytesPerRow + x * 4)
                            let a = pixel.advanced(by: 3).pointee
                            
                            pixel.advanced(by: 0).pointee = a
                            pixel.advanced(by: 1).pointee = a
                            pixel.advanced(by: 2).pointee = a
                            pixel.advanced(by: 3).pointee = a
                        }
                    }
                }
                return frameDuration
            }, proposedWidth: width, proposedHeight: height, insertKeyframe: i == 0 || keyframeOnly)
            
            if firstFrameOnly {
                break
            }
        }
        
        writer.finish()
    }
    
    writer.queue.async(work)
}

public func cacheStillSticker(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter, customColor: UIColor?) {
    let work: () -> Void = {
        if let data = try? Data(contentsOf: URL(fileURLWithPath: path)), let image = WebP.convert(fromWebP: data) {
            writer.add(with: { surface in
                guard let context = DrawingContext(size: CGSize(width: CGFloat(surface.width), height: CGFloat(surface.height)), scale: 1.0, opaque: false, clear: true, bytesPerRow: surface.bytesPerRow) else {
                    return 1.0
                }
                context.withFlippedContext { c in
                    UIGraphicsPushContext(c)
                    
                    if let customColor = customColor {
                        c.setFillColor(customColor.cgColor)
                        c.setBlendMode(.sourceIn)
                    }
                    
                    c.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: context.size))
                    UIGraphicsPopContext()
                }
                memcpy(surface.argb, context.bytes, surface.height * surface.bytesPerRow)
                return 1.0
            }, proposedWidth: width, proposedHeight: height, insertKeyframe: true)
        }
        
        writer.finish()
    }
    
    writer.queue.async(work)
}