/*
 Copyright (c) 2020 Swift Models Generated from JSON powered by http://www.json4swift.com

 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 For support, please feel free to contact me at https://www.linkedin.com/in/syedabsar

 */

import Foundation
import Kingfisher
import KingfisherWebP
import Photos

import ObjectMapper
import RealmSwift
import BFCommonKit

public class PQEditVisionTrackMaterialsModel: PQEditBaseModel {
    @objc dynamic public var width: Float = 0
    @objc dynamic public var height: Float = 0
    @objc public var itemWidth: Float = 0
    @objc public var itemHeight: Float = 0
    // 搜索素材来源
    @objc dynamic public var sourceType: Int = 0
    @objc dynamic public var type: String = ""
    @objc dynamic public var canvasFillType: String = ""

    @objc dynamic public var materialType: String = ""

    // 选择素材的时候会给值，这里是素材的真实时长
    @objc dynamic public var duration: Float64 = 0
    // 公式计算出来的逻辑显示时长
    @objc public var aptDuration: Float64 = 0

    @objc dynamic public var id: Int64 = 0
    @objc dynamic public var materialLayer: PQEditMaterialLayerModel?
    @objc dynamic public var materialEffect: PQEditMaterialEffectModel?
    
    //整体时间线中显示的开始和结束时间 (showtime) e.g. 10s - 20s
    @objc dynamic public var timelineIn: Float64 = 0
    @objc dynamic public var timelineOut: Float64 = 0
    //取原视频素材的截取时间(cliptime) e.g.  5s - 10s
    @objc dynamic public var model_in: Float64 = 0
    @objc dynamic public var out: Float64 = 0
    
    
     
    /*  设置播放速率 60FPS 范围 0 - 16.6(理论值) rate  正常速度为1.0；小于为慢速；大于为快速。但不能高于解码速度1-2ms硬解一帧
     原视频为：120FPS
     最大倍数：理想情况 = 1000 / 120 = 8.3 倍
             不理想情况 = 500 / 120 = 4.1

     原视频为：60FPS
     最大倍数：理想情况 = 1000 / 60 = 16.6 倍
             不理想情况 = 500 / 60 =  8.2
     */
    @objc dynamic public var speedRate: Float = 1
    
    @objc dynamic public var volumeGain: Float64 = 0
    @objc dynamic public var subtitleInfo: PQEditSubtitleInfoModel?
    @objc dynamic public var materialDurationFit: PQEditmaterialDurationFitModel?
    @objc dynamic public var materialSizeClip: PQEditMaterialSizeClipModel?
    @objc dynamic public var materialPosition: PQEditMaterialPositionModel?

    // -----------------------地址相关属性 本地地址都是 URI
    // 素材的外网 URL 我方服务器的外网地址 ,客户端不会赋值 会在 getDraftInfo API 中返回，是服务器自动拼接生成的。XXXXXX 素材封面都是根据这个地址现取的
    @objc dynamic public var materialUrl: String = ""

    // 这个是给网络素材库用的下载地址，其它地方都使用 materialUrl
    public var netResUrl: String = ""
    public var netResCoverImageURL: String?

    // 文件本地地址 URI
    @objc dynamic public var locationPath: String = "" {
        didSet {
            BFLog(message: "如果是全路径就有问题XXXX 设置了新值为：locationPath\(locationPath)")
        }
    }

    // --------------------------

    // add by ak 业务逻辑扩展字段
    // 是否为网络素材本地
    public var isNetworkMaterial: Bool = false
    public var isSelected: Bool = false // 是否被选中

    // 这里不会给值了
    public var asset: PHAsset? // 视频资源
    public var PHImageRequestID : Int32?
    public var selectedIndex: Int = 1 // 选中的index
    // 图片 和GIF 原数据 这里可能不在使用了
    public var originalData: Data?
    // 封面 仅本地相册显示封面使用
    public var coverImageUI: UIImage?
    public var downloadState: downloadState = .downloading
    public var localSearchId: String? // 本地每次搜索ID
    public var sliceId: String? // 搜索素材视频id
    public var searchId: String? // 每次搜索ID
    public var searchResourceId: String? // 搜索资源ID
    public var outSideChannel: String = ""
    public var outSideVideoId: String = ""
    public var status: inputStatus = .recordSuccess
    
    //视频素材被切分的段数，视频素材才有效，默认为1 不切分
    public var clipCount:Int = 1

    deinit {
        BFLog(1, message: "sticker release")
    }
   public required init() {
        super.init()
        materialDurationFit = PQEditmaterialDurationFitModel()
        materialSizeClip = PQEditMaterialSizeClipModel()
        materialPosition = PQEditMaterialPositionModel()
    }

    required convenience public init?(map _: Map) {
        self.init()
    }

    public  override func mapping(map: Map) {
        width <- map["width"]
        height <- map["height"]
        sourceType <- map["sourceType"]
        type <- map["type"]
        canvasFillType <- map["canvasFillType"]
        materialUrl <- map["materialUrl"]

        materialType <- map["materialType"]
        duration <- (map["duration"], timeTransform)
        id <- map["id"]
        materialLayer <- map["materialLayer"]
        materialEffect <- map["materialEffect"]
        timelineIn <- (map["timelineIn"], timeTransform)

        timelineOut <- (map["timelineOut"], timeTransform)

        model_in <- (map["in"], timeTransform)
        out <- (map["out"], timeTransform)
        volumeGain <- (map["volumeGain"], volumeGainTransform)
        subtitleInfo <- map["subtitleInfo"]
        materialDurationFit <- map["materialDurationFit"]
        materialSizeClip <- map["materialSizeClip"]
        materialPosition <- map["materialPosition"]
//        netResUrl <- map["netResUrl"]
//        netResCoverImageURL <- map["netResCoverImageURL"]
        locationPath <- map["locationPath"]

        aptDuration <- map["aptDuration"]
        outSideVideoId <- map["outSideVideoId"]
        outSideChannel <- map["outSideChannel"]
    }

    // 视频素材有无裁剪过，时长计算就不一样了
   public  func videoIsCrop() -> Bool {
        return (type == StickerType.VIDEO.rawValue && (model_in != 0 || out != 0))
    }

    // 生成默认值
   public  func generateDefaultValues() {
        if materialDurationFit?.fitType.count == 0 {
            materialDurationFit?.fitType = adapterMode.loopAuto.rawValue
        }

        if canvasFillType.count == 0 {
            canvasFillType = stickerContentMode.aspectFitStr.rawValue
        }
    }

    /// 初始化
    /// - Parameter jsonDict: <#jsonDict description#>
   public convenience init(jsonDict: [String: Any]) {
        self.init()
        if jsonDict.keys.contains("width") {
            width = Float(CGFloat(Double("\(jsonDict["width"] ?? "")") ?? 0))
        }
        if jsonDict.keys.contains("height") {
            height = Float(CGFloat(Double("\(jsonDict["height"] ?? "")") ?? 0))
        }
        if jsonDict.keys.contains("imageUrl"), !(jsonDict["imageUrl"] is NSNull), "\(jsonDict["imageUrl"] ?? "")" != "<null>" {
            netResCoverImageURL = "\(jsonDict["imageUrl"] ?? "")"
        }
        if jsonDict.keys.contains("gifUrl"), !(jsonDict["gifUrl"] is NSNull), "\(jsonDict["gifUrl"] ?? "")" != "<null>" {
            netResCoverImageURL = "\(jsonDict["gifUrl"] ?? "")"
        }
        if jsonDict.keys.contains("coversImageUrl"), !(jsonDict["coversImageUrl"] is NSNull), "\(jsonDict["coversImageUrl"] ?? "")" != "<null>" {
            netResCoverImageURL = "\(jsonDict["coversImageUrl"] ?? "")"
        }
        if jsonDict.keys.contains("videoUrl") {
            netResUrl = "\(jsonDict["videoUrl"] ?? "")"
        }
        if jsonDict.keys.contains("duration") {
            duration = Double((Int("\(jsonDict["duration"] ?? "0")") ?? 0) / 1_000_000)
            out = duration
        }
        if jsonDict.keys.contains("id") {
            searchResourceId = "\(jsonDict["id"] ?? "")"
        }
        if jsonDict.keys.contains("searchId") {
            searchId = "\(jsonDict["searchId"] ?? "")"
        }
        if jsonDict.keys.contains("sliceId") {
            sliceId = "\(jsonDict["sliceId"] ?? "")"
        }
        if jsonDict.keys.contains("sourceType") {
            sourceType = Int("\(jsonDict["sourceType"] ?? "1")") ?? 0
        }

        if jsonDict.keys.contains("outSideVideoId"), "\(jsonDict["outSideVideoId"] ?? "")" != "<null>" {
            outSideVideoId = "\(jsonDict["outSideVideoId"] ?? "")"
        }

        if jsonDict.keys.contains("outSideChannel"), "\(jsonDict["outSideChannel"] ?? "")" != "<null>" {
            outSideChannel = "\(jsonDict["outSideChannel"] ?? "")"
        }

        itemWidth = Float((cScreenWidth - 16 * 4) / 3)
        itemHeight = itemWidth * (height / (width == 0 ? 1 : width))
    }

    /// 素材是否相等
    /// - Parameter newMaterial: <#newMaterial description#>
    /// - Returns: <#description#>
   public  func isEqualMaterial(newMaterial: PQEditVisionTrackMaterialsModel?) -> Bool {
        if newMaterial == nil {
            BFLog(message: "素材对比为空：material = \(String(describing: newMaterial))")
            return false
        }
        if asset != nil && newMaterial?.asset != nil && asset == newMaterial?.asset {
            BFLog(message: "素材对比相等：asset = \(asset!)--\(String(describing: newMaterial?.asset))")
            return true
        }
        if (netResCoverImageURL != nil && (netResCoverImageURL?.count ?? 0) > 0) && (newMaterial?.netResCoverImageURL != nil && (newMaterial?.netResCoverImageURL?.count ?? 0) > 0) && netResCoverImageURL == newMaterial?.netResCoverImageURL {
            BFLog(message: "素材对比相等：netResCoverImageURL = \(netResCoverImageURL!)--\(String(describing: newMaterial?.netResCoverImageURL))")
            return true
        }
        if (materialUrl.count > 0) && ((newMaterial?.materialUrl.count ?? 0) > 0) && materialUrl == newMaterial?.materialUrl {
            BFLog(message: "素材对比相等：materialUrl = \(materialUrl)--\(String(describing: newMaterial?.materialUrl))")
            return true
        }
        BFLog(message: "素材对比不相等：asset = \(String(describing: asset))--\(String(describing: newMaterial?.asset)),netResCoverImageURL = \(String(describing: netResCoverImageURL))--\(String(describing: newMaterial?.netResCoverImageURL)),materialUrl = \(materialUrl)--\(String(describing: newMaterial?.materialUrl))")
        return false
    }

   public  func getCoverImage() -> UIImage? {
        if coverImageUI != nil {
            BFLog(message: "已经有封面了")
            return coverImageUI
        }
        if locationPath.count == 0 {
            BFLog(message: "本地地址为空可能没有下载完成！！")
            return nil
        }
        BFLog(message: " locationPath is\(documensDirectory + locationPath)")
        if type != StickerType.VIDEO.rawValue {
            var coverImage = UIImage(contentsOfFile: documensDirectory + locationPath)

            if coverImage == nil {
                // 有可能是 WEBP
                var fileData: Data?
                if fileIsExists(filePath: documensDirectory + locationPath) {
                    fileData = try! Data(contentsOf: URL(fileURLWithPath: documensDirectory + locationPath))
                }
                if fileData != nil && (fileData?.count ?? 0) > 0 && fileData?.isWebPFormat ?? false {
                    BFLog(message: "这个资源为web!")
                    coverImage = WebPProcessor.default.process(item: ImageProcessItem.data(fileData!), options: KingfisherParsedOptionsInfo([.onlyLoadFirstFrame, .scaleFactor(1)]))
                }
            }

            return coverImage
        } else {
            if coverImageUI != nil {
                BFLog(message: "已经有封面了")
                return coverImageUI
            } else {
                return PQVideoSnapshotUtil.videoSnapshot(videoURL: URL(fileURLWithPath: documensDirectory + locationPath), time: 0)
            }
        }
    }
    public override func copy(with zone: NSZone? = nil) -> Any {
        let temp = PQEditVisionTrackMaterialsModel.init()
       
        temp.width = width
        
        temp.height = height
        temp.itemWidth = itemWidth
        temp.itemHeight = itemHeight
        temp.sourceType = sourceType
        temp.type = type
        temp.canvasFillType = canvasFillType
        temp.materialType = materialType
        temp.duration = duration
        temp.aptDuration = aptDuration
        temp.id = id
        temp.materialLayer = materialLayer
        temp.materialEffect = materialEffect
        temp.timelineIn = timelineIn
        temp.timelineOut = timelineOut
        temp.model_in = model_in
        temp.out = out
        temp.speedRate = speedRate
        temp.volumeGain = volumeGain
        temp.materialUrl = materialUrl
        temp.netResUrl = netResUrl
        temp.netResCoverImageURL = netResCoverImageURL
        temp.locationPath = locationPath
 
        return temp
    }
}
