//
//  PQVoiceModel.swift
//  PQSpeed
//
//  Created by ak on 2020/8/18.
//  Copyright © 2020 BytesFlow. All rights reserved.
//

import Foundation
import BFCommonKit

public enum voiceStatue: Int {
    case isLoading = 0 // 加载中
    case isPlaying = 1 // 播放中
    case isNormal = 2 // 正常状态
    case isSelected = 3 // 选中状态，有红框 字红色 ，别的都没有
    case isPause = 4 // 播放状态暂停中
}

open class PQVoiceModel: NSObject, NSCopying {
    public var name: String = ""
    // 对应接口的 KEY
    public var voice: String = ""
    public var cateId: Int = 0
    // 性别
    public var gender: Int = 0
    public var avatarUrl: String = ""
    public var channel: String = "aliyun" // aliyun , azure
    // 是否为精品
    public var qualityFlag: Int = 0
    // 微软语音设置
    public var azureStyleConfig: [PQAzureStyleModel] = Array()
    // 声音文件沙盒位置 是 URI
    public var wavFilePath: String!

    // 是否收藏
    public var isFavorite: Bool = false
    // 是否在加载状态 是否在播放状态f
    public var voiceStatue: voiceStatue = .isNormal

    // 收藏 ID
    public var favoriteId: Int = 0

    public var speedRate: Float = 1.0
    public var pitchRate: Float = 0
    public var azureStyle: String = "general"

    public var isSelected: Bool = false // 是否被选中
    public  var isPlaying: Bool = false // 是否在播放
    public var itemWidth: CGFloat = 0 // 元素宽度
    public var materialUrl: String? // 播放地址
    public var localPath: String? // 本地存储地址
    public var duration: String? // 时长
    public var currentTime: Float64? // 当前已播放时长
    public var uniqueId: Int = 0 // 背景音乐ID
    public var materialId: String? // 保存发音人后素材IDmaterialUrl
    public var volume: Int = 0 // 0-100 素材音量
    public var startTime: Float64 = 0 // 开始时间
    public var suggestRhythmStartTime: Float64  = 0 //推荐起始点
    public var endTime: Float64 = 0 // 结束时间
    public var createTimestamp: Int64 = 0 // 创建时间
    public var voiceType: String = VOICETYPT.PRODUCE.rawValue // 音乐类型
    public  var accompanimentPath: String? // 伴奏地址
    public var musicId: String? // 音乐ID
    public var musicLabels: String? // 标签
    public var musicName: String? // 歌名
    public var musicPath: String? // 音乐地址
    public var musicSinger: String? // 歌手
    public var originType: Int = 1 // 音乐来源: 1上传, 2爬取
    public var sortNum: Int = 0 // 排序值
    public var vodAccompanimentMediaId: String? // 伴奏vod mediaId
    public var vodMusicMediaId: String? // 音乐vod mediaId
    // add by ak json 结构化数据传值使用
    public var wavfileDuration: Float64 = 0
    public var selectVoiceType: Int = 1 // 选择的声音类型，1：原声 ，2：背景声
    // 卡点视频-分类信息
    public var tagsInfo: PQStuckPointMusicTagsModel?
    // 卡点视频-卡点时间数据
    public var rhythmSdata: [PQStuckPointTimesModel] = Array<PQStuckPointTimesModel>.init()
    // 卡点视频-默认卡点速度（1：快节奏，2：适中，3：慢节奏） ,
    public var speed: Int = 2
    // 卡点视频-卡点音乐入点
    public var rhythmMusicIn: Float64 = 0
    // 卡点视频-卡点音乐出点
    public var rhythmMusicOut: Float64 = 0
    // 卡点视频-源项目ID(从那个项目做同款)
    public var originProjectId: String?
    
    //缓存使用的所在的分类 ID 不能用 tagsInfo 的 一首歌有可能在多个分类当中
    public var cacheTagID:Int64?
    public func copy(with _: NSZone? = nil) -> Any {
        let voice = PQVoiceModel()
        voice.name = name
        voice.channel = channel
        voice.azureStyle = azureStyle
        voice.voice = self.voice
        voice.cateId = cateId
        voice.gender = gender
        voice.duration = duration
        voice.avatarUrl = avatarUrl
        voice.wavFilePath = wavFilePath
        voice.isFavorite = isFavorite
        voice.isSelected = isSelected
        voice.voiceStatue = voiceStatue
        voice.speedRate = speedRate
        voice.pitchRate = pitchRate
        voice.qualityFlag = qualityFlag
//        voice.azureStyleConfig = azureStyleConfig

        // ui 使用
        voice.isSelected = isSelected
        voice.isPlaying = isPlaying
        voice.itemWidth = itemWidth
        voice.materialUrl = materialUrl
        voice.localPath = localPath

        voice.duration = duration
        voice.currentTime = currentTime
        voice.uniqueId = uniqueId
        voice.volume = volume
        voice.startTime = startTime
        voice.endTime = endTime
        voice.createTimestamp = createTimestamp
        voice.voiceType = voiceType
        voice.accompanimentPath = accompanimentPath
        voice.musicId = musicId
        voice.musicLabels = musicLabels
        voice.musicName = musicName
        voice.musicPath = musicPath
        voice.musicSinger = musicSinger
        voice.originType = originType
        voice.sortNum = sortNum
        voice.vodAccompanimentMediaId = vodAccompanimentMediaId
        voice.vodMusicMediaId = vodMusicMediaId
        return voice
    }

   public override init() {
        super.init()
    }

    public init(jsonDict: [String: Any]) {
        super.init()
        if jsonDict.keys.contains("name"), "\(jsonDict["name"] ?? "")" != "<null>" {
            name = "\(jsonDict["name"] ?? "")"
        }
        if jsonDict.keys.contains("cateName"), "\(jsonDict["cateName"] ?? "")" != "<null>" {
            name = "\(jsonDict["cateName"] ?? "")"
        }
        if jsonDict.keys.contains("coverUrl") {
            avatarUrl = "\(jsonDict["coverUrl"] ?? "")"
        }
        if jsonDict.keys.contains("avatarUrl") {
            avatarUrl = "\(jsonDict["avatarUrl"] ?? "")"
        }
        if jsonDict.keys.contains("coverImgPath") {
            avatarUrl = "\(jsonDict["coverImgPath"] ?? "")"
        }
        if jsonDict.keys.contains("bgmId") {
            uniqueId = Int("\(jsonDict["bgmId"] ?? "0")") ?? 0
        }

        if jsonDict.keys.contains("gender") {
            gender = Int("\(jsonDict["gender"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("id") {
            uniqueId = Int("\(jsonDict["id"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("cateId") {
            cateId = Int("\(jsonDict["cateId"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("cid") {
            cateId = Int("\(jsonDict["cid"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("createTimestamp") {
            createTimestamp = Int64("\(jsonDict["createTimestamp"] ?? "0")") ?? 0
        }
        if name.count > 0 {
            itemWidth = sizeWithText(text: name, font: UIFont.systemFont(ofSize: 14, weight: .semibold), size: CGSize(width: cDefaultMargin * 10, height: cDefaultMargin * 4)).width + cDefaultMargin * 3
        }
        if jsonDict.keys.contains("favoriteStatus") {
            isFavorite = "\(jsonDict["favoriteStatus"] ?? "0")" == "1"
        }
        if jsonDict.keys.contains("materialUrl") {
            materialUrl = "\(jsonDict["materialUrl"] ?? "")"
        }
        if jsonDict.keys.contains("duration") {
            duration = "\(jsonDict["duration"] ?? "")"
            if (Float64("\(duration ?? "0")") ?? 0) < 1_000_000 {
                duration = "\(Float64("\(duration ?? "0")") ?? 0)"
            } else {
                duration = "\((Float64("\(duration ?? "0")") ?? 0) / 1_000_000)"
            }
        }
        if jsonDict.keys.contains("accompanimentPath") {
            accompanimentPath = "\(jsonDict["accompanimentPath"] ?? "")"
        }
        if jsonDict.keys.contains("musicId") {
            musicId = "\(jsonDict["musicId"] ?? "")"
        }
        if jsonDict.keys.contains("musicLabels") {
            musicLabels = "\(jsonDict["musicLabels"] ?? "")"
        }
        if jsonDict.keys.contains("musicName") {
            musicName = "\(jsonDict["musicName"] ?? "")"
        }
        if jsonDict.keys.contains("musicPath") {
            musicPath = "\(jsonDict["musicPath"] ?? "")"
        }
        if jsonDict.keys.contains("coverMusicPath") {
            musicPath = "\(jsonDict["coverMusicPath"] ?? "")"
        }
        if jsonDict.keys.contains("musicSinger"), "\(jsonDict["musicSinger"] ?? "")" != "<null>" {
            musicSinger = "\(jsonDict["musicSinger"] ?? "")"
        }
        if jsonDict.keys.contains("author"), "\(jsonDict["author"] ?? "")" != "<null>" {
            musicSinger = "\(jsonDict["author"] ?? "")"
        }
        if jsonDict.keys.contains("originType") {
            originType = Int("\(jsonDict["originType"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("sortNum") {
            sortNum = Int("\(jsonDict["sortNum"] ?? "0")") ?? 0
        }
        if jsonDict.keys.contains("vodAccompanimentMediaId") {
            vodAccompanimentMediaId = "\(jsonDict["vodAccompanimentMediaId"] ?? "")"
        }
        if jsonDict.keys.contains("vodMusicMediaId") {
            vodAccompanimentMediaId = "\(jsonDict["vodMusicMediaId"] ?? "")"
        }
        if jsonDict.keys.contains("musicTagInfos") {
            let musicTagInfos = jsonDict["musicTagInfos"] as? [String: Any]
            if musicTagInfos != nil, (musicTagInfos?.keys.count ?? 0) > 0 {
                tagsInfo = PQStuckPointMusicTagsModel(jsonDict: musicTagInfos!)
            }
        }
        if jsonDict.keys.contains("rhythmSdata"), "\(jsonDict["rhythmSdata"] ?? "")".count > 0, "\(jsonDict["rhythmSdata"] ?? "")" != "<null>" {
            let tempArr = jsonStringToArray(jsonString: "\(jsonDict["rhythmSdata"] ?? "")")
            if tempArr != nil, (tempArr?.count ?? 0) > 0 {
                tempArr?.forEach { sdata in
                    let tempTimesModel: PQStuckPointTimesModel = PQStuckPointTimesModel(jsonDict: (sdata as? [String: Any]) ?? [:])
                    rhythmSdata.append(tempTimesModel)
                }
            }
        }
        if jsonDict.keys.contains("suggestRhythmStart") {
            startTime = (Float64("\(jsonDict["suggestRhythmStart"] ?? "0")") ?? 0) / 1_000_000
        }
        
        if jsonDict.keys.contains("suggestRhythmStart") {
            suggestRhythmStartTime = (Float64("\(jsonDict["suggestRhythmStart"] ?? "0")") ?? 0) / 1_000_000
        }
        
        if jsonDict.keys.contains("suggestRhythmEnd") {
            endTime = (Float64("\(jsonDict["suggestRhythmEnd"] ?? "0")") ?? 0) / 1_000_000
        }
        if jsonDict.keys.contains("speed"), "\(jsonDict["speed"] ?? "")" != "<null>" {
            speed = Int("\(jsonDict["speed"] ?? "2")") ?? 2
        }
        if jsonDict.keys.contains("rhythmMusicIn") {
            rhythmMusicIn = (Float64("\(jsonDict["rhythmMusicIn"] ?? "0")") ?? 0) / 1_000_000
        }
        if jsonDict.keys.contains("rhythmMusicOut") {
            rhythmMusicOut = (Float64("\(jsonDict["rhythmMusicOut"] ?? "0")") ?? 0) / 1_000_000
        }
        if jsonDict.keys.contains("originProjectId"), "\(jsonDict["originProjectId"] ?? "")" != "<null>" {
            originProjectId = "\(jsonDict["originProjectId"] ?? "")"
        }
        if jsonDict.keys.contains("projectId"), "\(jsonDict["projectId"] ?? "")" != "<null>" {
            originProjectId = "\(jsonDict["projectId"] ?? "")"
        }
    }

    /// 计算卡点时长 策略1 ：
    /// - Parameters:
    ///   - videoCount: 视频个数
    ///   - imageCount: 图片个数
    /// - Returns: <#description#>
    public func stuckPointCuttingTime(videoCount _: Int, imageCount: Int, totalDuration: Float64) -> Float64 {
        if totalDuration <= 0 {
            return 0
        }
        // 默认比例
        let rate: Float64 = 1.5
        // 音乐最大时长
        let MaxM: Float64 = 40
        // 音乐最小时长
        let MinM: Float64 = 10
        // 视频个数
//        var V1: Float64 = Float64(videoCount)
        // 图片个数
        let V2: Float64 = Float64(imageCount)
        // 视频总时长
        let V1T: Float64 = totalDuration - V2
        if endTime <= startTime {
            endTime = startTime + MaxM
        }
        // 推荐音乐时长
        var M: Float64 = endTime - startTime
        // 音频段数
//        let MC: Float64 = Float64(rhythmSdata.first?.pointTimes.count ?? 1)
        // 档位时长平均值
//        let MST: Float64 = (Float64(duration ?? "0") ?? 0) / MC
        // 从推荐点位开始speed*V2 的点位个数的时长/V2
        let startS: Float64 = Float64(Double(rhythmSdata.first?.pointTimes.first ?? 0) / 1_000_000.0)
        var endS: Float64 = Float64(Double(rhythmSdata.first?.pointTimes.last ?? 0) / 1_000_000.0)
        if V2 > 0, speed > 0, Float64(rhythmSdata.first?.pointTimes.count ?? 0) > (V2 * Float64(speed) + 2) {
            endS = Float64(Double(rhythmSdata.first?.pointTimes[Int(V2 * Float64(speed) + 2)] ?? 0) / 1_000_000.0)
        }
        let MST: Float64 = V2 <= 0 ? 0 : (endS - startS) / V2
        if (V2 * MST + V1T / 2) >= MaxM {
            M = MaxM
        } else if (V2 * MST + V1T / 2) >= MinM && MaxM > (V2 * MST + V1T / 2) {
            M = V2 * MST + V1T / 2
        } else if (V2 * MST + V1T / 2) <= MinM && (V2 * MST + V1T) * rate >= MinM {
            M = (V2 * MST + V1T) * rate
        } else if (V2 * MST + V1T) * rate < MinM {
            M = MinM
        }
        // 限制卡点时长最大值不能超过duration
        if (M + startTime) > endTime {
            M = endTime - startTime
        } else if (M + startTime) > (Float64(duration ?? "0") ?? 0) {
            M = (Float64(duration ?? "0") ?? 0) - startTime
        }
        BFLog(message: "计算当前裁剪时长：\(M),开始时间：\(startTime),结束时间：\(endTime),总时长:\(Float64(duration ?? "0") ?? 0)")
        return M
    }
}
