//
//  PQGifFilter.swift
//  GPUImage_macOS
//
//  Created by ak on 2020/8/17.
//  Copyright © 2020 Sunset Lake Software LLC. All rights reserved.
//

import Foundation
import UIKit
import BFCommonKit

open class PQGifFilter: PQBaseFilter {
    var gifImageCount: Int = 0

    var imageTexture: GLuint = 0

    var gifSize: CGSize = .zero

    var mSticker: PQEditVisionTrackMaterialsModel?

    // 开始时间，有可能不是从0开始的 要处理到从0开始
    var beginTime: Float64 = 0

    // 原始的所有 gif 图片
    var mGifImages: [UIImage] = []
    var mDuration: Double = 0

    // gif 要显示的 每一帧的时间
    var delayTime: Double = 0

    init(sticker: PQEditVisionTrackMaterialsModel) {
        super.init(fragmentShader: PassthroughFragmentShader, numberOfInputs: 1)
        mSticker = sticker

        BFLog(2, message: "gif file path \(mSticker?.locationPath ?? "")")
        var gifData: Data!
        autoreleasepool {
            do {
                gifData = try Data(contentsOf: URL(fileURLWithPath: documensDirectory + (mSticker?.locationPath ?? "")))
            } catch {
                print("loading gif images file error")
                return
            }
        }

        if gifData == nil {
            BFLog(message: "gif数据有问题！")
            return
        }
        PQPHAssetVideoParaseUtil.parasGIFImage(data: gifData) { [weak self] _, images, duration in

            self?.mGifImages = images ?? []
            self?.mDuration = duration ?? 0
            BFLog(2, message: "gif 原始时长 \(String(describing: duration)) 逻辑时长: \(String(describing: self?.mSticker?.aptDuration)) 帧数:\(String(describing: images?.count))")

            if images!.count > 0 {
                self?.gifSize = images!.first!.size
            }

            // 每一帧的时间 速度自适应
            self?.delayTime = (self?.mSticker?.aptDuration ?? 1) / Double(self?.mGifImages.count ?? 1)
            // 不改变速度还是原速度

            if self?.mSticker?.materialDurationFit?.fitType == adapterMode.loopAuto.rawValue || self?.mSticker?.materialDurationFit?.fitType == adapterMode.staticFrame.rawValue {
                self?.delayTime = self?.mDuration ?? 1 / Double(self?.mGifImages.count ?? 1)
                BFLog(message: "正常速度每一帧的时间：\(String(describing: self?.delayTime))")
            }
            sharedImageProcessingContext.runOperationSynchronously {
                // ( 提前渲染一帧
                if self?.mGifImages.count ?? 0 > 0, let image = self?.mGifImages[0].cgImage{
                    self?.imageTexture = PQGPUImageTools.setupTexture(image: image)
                }

                gifData = nil
            }
        }
    }

    func updateImages(_ currTime: Float64) {
        autoreleasepool {
            if mGifImages.count == 0 {
                BFLog(2, message: "gif 文件有问题 一帧都没有")
                return
            }
            if delayTime <= 0 {
                BFLog(2, message: "gif 时间计算出错")
                return
            }
            // 判断显示哪一帧
            var gifIndex = delayTime <= 0 ? 0 : Int(((currTime >= beginTime) ? currTime - beginTime : currTime) / delayTime)
            if mSticker?.materialDurationFit?.fitType == adapterMode.staticFrame.rawValue && gifIndex >= mGifImages.count { // 定帧
                BFLog(2, message: "定帧效果 \(gifIndex)")
                imageTexture = PQGPUImageTools.setupTexture(image: (mGifImages.last?.cgImage)!)
                return
            }

            if gifIndex >= mGifImages.count && mSticker?.materialDurationFit?.fitType == adapterMode.loopAuto.rawValue { // 自动循环重新计算开始时间 达到循环效果
                BFLog(2, message: "自动循环效果")
                gifIndex = gifIndex % mGifImages.count
            }

            if gifIndex >= mGifImages.count {
                gifIndex = mGifImages.count - 1
            }

            // 显示的帧
            imageTexture = PQGPUImageTools.setupTexture(image: mGifImages[gifIndex].cgImage!)
        }
    }

    override public func newFramebufferAvailable(_ framebuffer: Framebuffer, fromSourceIndex: UInt) {
        autoreleasepool {
            super.newFramebufferAvailable(framebuffer, fromSourceIndex: fromSourceIndex)

            let currTime = CMTimeGetSeconds(CMTime(value: framebuffer.timingStyle.timestamp!.value, timescale: framebuffer.timingStyle.timestamp!.timescale))

            if currTime >= mSticker!.timelineIn, currTime <= mSticker!.timelineOut {
                // 更新gif下一帧图片
                if beginTime == 0 {
                    beginTime = currTime
                }

                updateImages(currTime)
            }
        }
    }

    override open func renderFrame() {
        autoreleasepool {
            let inputFramebuffer: Framebuffer = inputFramebuffers[0]!
            let inputSize = inputFramebuffer.sizeForTargetOrientation(.portrait)

            let currTime = CMTimeGetSeconds(CMTime(value: inputFramebuffer.timingStyle.timestamp!.value, timescale: inputFramebuffer.timingStyle.timestamp!.timescale))
            BFLog(2, message: "gif filter 当前时间: \(currTime) ")

            // 原有画布
            renderFramebuffer = sharedImageProcessingContext.framebufferCache.requestFramebufferWithProperties(orientation: .portrait, size: inputSize, stencil: false)

            let textureProperties = InputTextureProperties(textureCoordinates: inputFramebuffer.orientation.rotationNeededForOrientation(.portrait).textureCoordinates(), texture: inputFramebuffer.texture)

            renderFramebuffer.activateFramebufferForRendering()
            clearFramebufferWithColor(backgroundColor)
            renderQuadWithShader(shader, uniformSettings: uniformSettings,
                                 vertexBufferObject: sharedImageProcessingContext.standardImageVBO, inputTextures: [textureProperties])
            releaseIncomingFramebuffers()

            if currTime >= mSticker!.timelineIn, currTime <= mSticker!.timelineOut {
                BFLog(2, message: " 显示gif当前时间: \(currTime) 开始时间：\(mSticker!.timelineIn) 结束时间：\(mSticker!.timelineOut)  ")

                // 绘制 image
                let textureCoordinates = PQGPUImageTools.getTextureCoordinates(sticker: mSticker!, textureSize: gifSize, cannvasSize: inputSize)

                let texturePropertiesimagetwo = InputTextureProperties(textureCoordinates: textureCoordinates, texture: imageTexture)

                let verticesPoint: [GLfloat] = PQGPUImageTools.getVerticesPoint(sticker: mSticker!, textureSize: gifSize, cannvasSize: inputSize)

                let gifBuffer: GLuint = PQGPUImageTools.NXGenerateVBO(for: verticesPoint)

                renderQuadWithShader(shader,
                                     uniformSettings: uniformSettings,
                                     vertexBufferObject: gifBuffer,
                                     inputTextures: [texturePropertiesimagetwo])
                releaseIncomingFramebuffers()

                PQGPUImageTools.deleteVBO(gifBuffer)

                // XXXXXXX 清空纹理,注意不清空显存会暴增
                glDeleteTextures(1, &imageTexture)
            } else {
                BFLog(2, message: " 不显示gif时: \(currTime) 开始时间：\(mSticker!.timelineIn) 结束时间：\(mSticker!.timelineOut)")
            }
        }
    }
}
