//
//  PQCommonMethodUtil.swift
//  PQSpeed
//
//  Created by lieyunye on 2020/5/29.
//  Copyright © 2020 BytesFlow. All rights reserved.
//

import AdSupport
import Alamofire
import Foundation
import KeychainAccess
import Kingfisher
import KingfisherWebP
import Photos
import Toast_Swift
/// Home文件地址
public let homeDirectory = NSHomeDirectory()
/// docdocumens文件地址
public let documensDirectory = homeDirectory + "/Documents"
/// library文件地址
public let libraryDirectory = homeDirectory + "/Library"

/// 本地存储资源地址
public let resourceDirectory = documensDirectory + "/Resource"
/// 播放视频缓冲本地沙河目录
public let videoCacheDirectory = resourceDirectory + "/VideoCache"
/// 相册视频导出到本地沙河目录
public let photoLibraryDirectory = resourceDirectory + "/PhotoLibrary/"
/// 背景音乐导出到本地沙河目录
public let bgMusicDirectory = resourceDirectory + "/BGMusic/"
/// 网络视频素材下载到本地沙河目录
public let downloadDirectory = resourceDirectory + "/Download/"
/// 网络图片、GIF 素材下载到本地沙河目录
public let downloadImagesDirectory = resourceDirectory + "/DownloadImages/"
/// 临时缓存本地沙河目录地址
public let tempDirectory = resourceDirectory + "/Temp/"
/// 导出声音的本地沙盒目录v
public let exportAudiosDirectory = resourceDirectory + "/ExportAudios/"
/// 导出合成视频的本地沙盒目录
public let exportVideosDirectory = resourceDirectory + "/ExportVideos/"
// 版本构建号
public let versionCode = "\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? "1")"
// 版本号
public let versionName = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "1.0.0")"
/// 创建目录文件
/// - Returns: <#description#>
public func createDirectory(path: String) {
    let fileManager = FileManager.default
    if !fileManager.fileExists(atPath: path) {
        try? fileManager.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
    }
}

/// 判断文件夹是否存在
/// - Parameter dicPath:文件夹 目录
public func directoryIsExists(dicPath: String) -> Bool {
    BFLog(message: " dir path is： \(dicPath)")
    var directoryExists = ObjCBool(false)
    let fileExists = FileManager.default.fileExists(atPath: dicPath, isDirectory: &directoryExists)
    return fileExists && directoryExists.boolValue
}

/// 判断文件是否存在
/// - Parameter filepath: 文件目录
public func fileIsExists(filePath: String) -> Bool {
    BFLog(message: "file path is： \(filePath)")

    let fileExists = FileManager.default.fileExists(atPath: filePath)
    return fileExists
}

/// 创建沙河文件地址
/// - Parameter url: 原地址
/// - Returns: <#description#>
public func createFilePath(url: String) -> Bool {
    let fileManager = FileManager.default
    if !fileManager.fileExists(atPath: url) {
        let isFinished = fileManager.createFile(atPath: url, contents: nil, attributes: nil)
        return isFinished
    }
    return true
}

public func cIPHONE_X() -> Bool {
    guard #available(iOS 11.0, *) else {
        return false
    }
    let isX = (UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) > 0
    return isX
}

/// 给按钮/imageView加载网络图片
///
/// - Parameters:
///   - url: 网络url
///   - mainView: 需要加载的视图
public func netImage(url: String, mainView: Any, placeholder: UIImage = UIImage().BF_Image(named: "placehold_image")) {
    if mainView is UIImageView {
        (mainView as! UIImageView).kf.setImage(with: URL(string: url), placeholder: placeholder, options: url.suffix(5) == ".webp" ? [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)] : nil, progressBlock: { _, _ in

        }) { _ in
        }
    } else if mainView is UIButton {
        (mainView as! UIButton).kf.setImage(with: URL(string: url), for: .normal, placeholder: placeholder, options: url.suffix(5) == ".webp" ? [.processor(WebPProcessor.default), .cacheSerializer(WebPSerializer.default)] : nil, progressBlock: { _, _ in

        }) { _ in
        }
    }
}

/** 获取Kingfisher缓存的图片的data */
public func kf_imageCacheData(originUrl: String) -> Data? {
    let diskCachePath = ImageCache.default.cachePath(forKey: originUrl)
    let data = try? Data(contentsOf: URL(fileURLWithPath: diskCachePath))
    return data
}

/** 获取Kingfisher缓存的图片 */
public func kf_imageCacheImage(originUrl: String, completeHandle: @escaping (_ image: UIImage?, _ error: Error?) -> Void) {
    ImageCache.default.retrieveImageInDiskCache(forKey: originUrl, options: [.cacheOriginalImage]) { result in
        DispatchQueue.main.async {
            switch result {
            case let .success(image):
                completeHandle(image, nil)
            case let .failure(error):
                completeHandle(nil, error)
            }
        }
    }
}

/** 打印 */
public func BFLog<T>(message: T) {
    let logger = NXLogger.shared

    logger.level = .info
    logger.ouput = .debuggerConsole

    logger.d(message as? String ?? "")
}

// MARK: 获取公共参数

public func commonParams() -> [String: Any] {
    let model = UIDevice.current.model
    let systemName = UIDevice.current.systemName
    let systemVersion = UIDevice.current.systemVersion
    let localizedModel = UIDevice.current.localizedModel
    let machineInfo: [String: Any] = [
        "model": model, "system": systemName + " " + systemVersion, "brand": localizedModel, "platform": "iOS", "networkType": networkStatus(), "clientIp": ipAddress(),
    ]
    var commParams: [String: Any] = [
        "appVersionCode": versionCode,
        "versionCode": versionCode,
        "system": systemName + " " + systemVersion,
        "systemVersion": systemName + " " + systemVersion,
        "appType": PQBFConfig.shared.appType,
        "appId": PQBFConfig.shared.appId,
        "machineCode": getMachineCode(),
        "networkType": networkStatus(),
        "ipAddress": ipAddress(),
        "clientTimestamp": Int64(Date().timeIntervalSince1970 * 1000),
        "platform": "iOS",
        "versionName": versionName,
//        "sessionId": PQSingletoMemoryUtil.shared.sessionId,
//        "subSessionId": PQSingletoMemoryUtil.shared.subSessionid ?? PQSingletoMemoryUtil.shared.sessionId,
        "mid": getMachineCode(),
        "machineInfo": dictionaryToJsonString(machineInfo) ?? "",
//        "abInfoData": dictionaryToJsonString(PQSingletoMemoryUtil.shared.abInfoData) ?? "",
        "requestId": getUniqueId(desc: "requestId"),
        "idfa": ASIdentifierManager.shared().advertisingIdentifier.uuidString,
        "idfv": UIDevice.current.identifierForVendor?.uuidString ?? "",
//        "deviceToken": PQSingletoMemoryUtil.shared.deviceToken,
    ]
//    if BFLoginUserInfo.shared.accessToken.count > 0 {
//        commParams["token"] = BFLoginUserInfo.shared.accessToken
//    }
//    if BFLoginUserInfo.shared.uid.count > 0 {
//        commParams["loginUid"] = BFLoginUserInfo.shared.uid
//        commParams["uid"] = BFLoginUserInfo.shared.uid
//    }
//    showAlertVc(title: "公参", message: dictionaryToJsonString(commParams))
    return commParams
}

/// 获取网络状态
/// - Returns: <#description#>
public func networkStatus() -> String {
    let status = NetworkReachabilityManager(host: "www.baidu.com")?.networkReachabilityStatus
    var statusStr: String!

    switch status {
    case .unknown:
        statusStr = "NETWORK_UNKNOWN"
    case .notReachable:
        statusStr = "NETWORK_NO"
    case .reachable(.wwan):
        statusStr = "4G"
    case .reachable(.ethernetOrWiFi):
        statusStr = "Wi-Fi"
    default:
        statusStr = "NETWORK_UNKNOWN"
    }
    return statusStr
}

/// 判断是否有网
/// - Returns: <#description#>
public func isNetConnected() -> Bool {
    return NetworkReachabilityManager(host: "www.baidu.com")?.networkReachabilityStatus != .notReachable
}

/// 获取ip地址
/// - Returns: <#description#>
public func ipAddress() -> String {
    var addresses = [String]()
    var ifaddr: UnsafeMutablePointer<ifaddrs>?
    if getifaddrs(&ifaddr) == 0 {
        var ptr = ifaddr
        while ptr != nil {
            let flags = Int32(ptr!.pointee.ifa_flags)
            var addr = ptr!.pointee.ifa_addr.pointee
            if (flags & (IFF_UP | IFF_RUNNING | IFF_LOOPBACK)) == (IFF_UP | IFF_RUNNING) {
                if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    if getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 {
                        if let address = String(validatingUTF8: hostname) {
                            addresses.append(address)
                        }
                    }
                }
            }
            ptr = ptr!.pointee.ifa_next
        }
        freeifaddrs(ifaddr)
    }
    return addresses.first ?? "0.0.0.0"
}

/// 生成唯一ID / 分享跟冷启动
/// - Parameter desc: <#desc description#>
/// - Returns: <#description#>
public func getUniqueId(desc: String) -> String {
    let timeStr: String = "\(Date().timeIntervalSince1970)"
    let uuid: String = getMachineCode()
    let code: String = "\(arc4random_uniform(1_000_000_000))"
    let uniqueId = (timeStr + desc + uuid + code).md5.md5
    BFLog(message: "生成唯一码:desc = \(desc),timeStr = \(timeStr),uuid = \(uuid),code = \(code),uniqueId = \(uniqueId)")
    return uniqueId
}

// MARK: 字典转字符串

public func dictionaryToJsonString(_ dic: [String: Any]) -> String? {
    BFLog(message: "dictionaryToJsonString = \(dic)")
    if !JSONSerialization.isValidJSONObject(dic) {
        return ""
    }
    guard let data = try? JSONSerialization.data(withJSONObject: dic, options: []) else {
        return ""
    }
    BFLog(message: "dictionaryToJsonString - data = \(data)")
    let str = String(data: data, encoding: String.Encoding.utf8)
    BFLog(message: "dictionaryToJsonString - str = \(String(describing: str))")
    return str
}

// MARK: 字符串转字典

public func jsonStringToDictionary(_ str: String) -> [String: Any]? {
    let data = str.data(using: String.Encoding.utf8)
    if data == nil {
        return [:]
    }
    if let dict = try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {
        return dict
    }
    return [:]
}

// MARK: 字符串转数组

public func jsonStringToArray(_ str: String) -> [[String: String]]? {
    let data = str.data(using: String.Encoding.utf8)
    if let array = try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? [[String: String]] {
        return array
    }
    return nil
}

/// 数组转为string
/// - Parameter array: <#array description#>
/// - Returns: <#description#>
public func arrayToJsonString(_ array: [Any]) -> String {
    if !JSONSerialization.isValidJSONObject(array) {
        BFLog(message: "无法解析String")
        return ""
    }
    let data: NSData! = try? JSONSerialization.data(withJSONObject: array, options: []) as NSData?
    let JSONString = NSString(data: data as Data, encoding: String.Encoding.utf8.rawValue)
    return JSONString! as String
}

/// jsonString转为数组
/// - Parameter jsonString: <#jsonString description#>
/// - Returns: <#description#>
public func jsonStringToArray(jsonString: String) -> [Any]? {
    let data = jsonString.data(using: String.Encoding.utf8)
    if data == nil {
        return nil
    }
    if let array = try? JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? [Any] {
        return array
    }
    return nil
}

/// 计算字符串大小
/// - Parameters:
///   - text: <#text description#>
///   - font: <#font description#>
///   - size: <#size description#>
/// - Returns: <#description#>
public func sizeWithText(text: String, font: UIFont, size: CGSize) -> CGSize {
    let attributes = [NSAttributedString.Key.font: font]
    let option = NSStringDrawingOptions.usesLineFragmentOrigin
    let rect: CGRect = text.boundingRect(with: size, options: option, attributes: attributes, context: nil)
    return rect.size
}

/// 根据行数计算字符串大小
/// - Parameters:
///   - text: <#text description#>
///   - numberOfLines: <#numberOfLines description#>
///   - font: <#font description#>
///   - maxSize: <#maxSize description#>
/// - Returns: <#description#>
public func sizeTextFits(attributedText: NSMutableAttributedString?, text: String?, numberOfLines: Int, font: UIFont, maxSize: CGSize) -> CGSize {
    var newSize: CGSize = CGSize(width: 0, height: 0)
    let label = UILabel(frame: CGRect.zero)
    label.font = font
    label.numberOfLines = numberOfLines
    if attributedText != nil {
        label.attributedText = attributedText
    } else {
        label.text = text
    }
    newSize = label.sizeThatFits(maxSize)

    return newSize
}

public func textNumberOfLines(text: String, font: UIFont, maxSize _: CGSize) -> Int {
    let label = UILabel(frame: CGRect.zero)
    label.font = font
    label.numberOfLines = 0
    label.text = text
    return label.numberOfLines
}

/// 生成渐变色
/// - Parameters:
///   - size: <#size description#>
///   - endPoint: <#endPoint description#>
///   - startColor: <#startColor description#>
///   - endColor: <#endColor description#>
/// - Returns: <#description#>
public func gradientColor(size: CGSize, endPoint: CGPoint, startColor: UIColor, endColor: UIColor) -> UIColor {
    let gradientLayer = CAGradientLayer()
    gradientLayer.frame = CGRect(origin: CGPoint(), size: size)
    gradientLayer.startPoint = CGPoint.zero
    gradientLayer.endPoint = endPoint
    gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
    UIGraphicsBeginImageContext(size)
    gradientLayer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()!
    return UIColor(patternImage: image)
}

/// 获取设备ID
/// - Returns: <#description#>
public func getMachineCode() -> String {
    let userInfo: [String: Any]? = jsonStringToDictionary(UserDefaults.standard.string(forKey: cUserInfoStorageKey) ?? "")
    if userInfo != nil && ((userInfo?.keys.contains("isVirtualUser") ?? false) && !(userInfo?["isVirtualUser"] is NSNull) && ((userInfo?["isVirtualUser"] as? Bool) ?? false)) && ((userInfo?.keys.contains("mid") ?? false) && !(userInfo?["mid"] is NSNull)) {
        BFLog(message: "虚拟账号mid：\("\(userInfo?["mid"] ?? "")")")
        return "\(userInfo?["mid"] ?? "")"
    }
    let keychain = Keychain(service: "com.piaoquan.pqspeed")
    var uuid: String = keychain["machineCode"] ?? ""
    if uuid.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
        uuid = NSUUID().uuidString
        keychain["machineCode"] = uuid
    }
    BFLog(message: "正式账号mid：\(uuid)")
    return uuid
}

/// 显示加载中视图
/// - Parameters:
///   - superView: <#superView description#>
///   - msg: <#msg description#>
/// - Returns: <#description#>
public func cShowHUB(superView: UIView?, msg: String?) {
    DispatchQueue.main.async {
        if superView == nil {
            if msg == nil {
                UIApplication.shared.keyWindow?.makeToastActivity(.center)
            } else {
                UIApplication.shared.keyWindow?.makeToast(msg, duration: 3.0, position: .center)
            }
        } else {
            if msg == nil {
                superView!.makeToastActivity(.center)
            } else {
                superView!.makeToast(msg, duration: 3.0, position: .center)
            }
        }
    }
}

/// 隐藏加载中视图
/// - Parameter superView: <#superView description#>
/// - Returns: <#description#>
public func cHiddenHUB(superView: UIView?) {
    DispatchQueue.main.async {
        if superView == nil {
            UIApplication.shared.keyWindow?.hideAllToasts()
            UIApplication.shared.keyWindow?.hideToastActivity()
        } else {
            superView!.hideAllToasts()
            superView?.hideToastActivity()
        }
    }
}

/// 获取存储值
/// - Parameter key: key description
/// - Returns: description
public func getUserDefaults(key: String) -> Any? {
    return UserDefaults.standard.object(forKey: key)
}

/// 存储数据
/// - Parameters:
///   - key: key description
///   - value: value description
/// - Returns: description
public func saveUserDefaults(key: String, value: String) {
    UserDefaults.standard.set(value, forKey: key)
    UserDefaults.standard.synchronize()
}

/// 存储数据带版本号
/// - Parameters:
///   - key: <#key description#>
///   - value: <#value description#>
public func saveUserDefaultsToJson(key: String, value: Any) {
    UserDefaults.standard.set(dictionaryToJsonString([key: value, "appVersionCode": versionCode, "versionName": versionName]), forKey: key)
    UserDefaults.standard.synchronize()
}

/// 获取数据带版本号
/// - Parameter key: <#key description#>
/// - Returns: <#description#>
public func getUserDefaultsForJson(key: String) -> Any? {
    let jsonStr = UserDefaults.standard.object(forKey: key)
    if jsonStr != nil {
        return jsonStringToDictionary(jsonStr as! String)?[key]
    }
    return UserDefaults.standard.object(forKey: key)
}

/// 清空数据
/// - Parameters:
///   - key: key description
///   - value: value description
/// - Returns: description
public func removeUserDefaults(key: String) {
    UserDefaults.standard.removeObject(forKey: key)
    UserDefaults.standard.synchronize()
}

/// 存储数据
/// - Parameters:
///   - key: key description
///   - value: value description
/// - Returns: description
public func saveUserDefaults(key: String, value: Any) {
    UserDefaults.standard.set(value, forKey: key)
    UserDefaults.standard.synchronize()
}

/// 保存自定义model   as NSArray  当 OBJ 是数组时不能使用 Array 要使用 NSArray
/// - Parameter object: <#object description#>
/// - Parameter key: <#key description#>
public func saveCustomObject(customObject object: NSCoding, key: String) {
    let encodedObject = NSKeyedArchiver.archivedData(withRootObject: object)
    UserDefaults.standard.set(encodedObject, forKey: key)
    UserDefaults.standard.synchronize()
    BFLog(message: "保存自定义类成功 key is \(key) \(encodedObject.count)")
}

/// 取自定义model
/// - Parameter key: <#key description#>
public func getCustomObject(forKey key: String) -> AnyObject? {
    let decodedObject = UserDefaults.standard.object(forKey: key) as? Data

    if decodedObject == nil {
        BFLog(message: "key is \(key)  decodedObject is nil")
    }
    if let decoded = decodedObject {
        let object = NSKeyedUnarchiver.unarchiveObject(with: decoded as Data)

        return object as AnyObject?
    }

    return nil
}

/// 添加通知
/// - Parameters:
///   - observer: <#observer description#>
///   - aSelectorName: <#aSelectorName description#>
///   - aName: <#aName description#>
///   - anObject: <#anObject description#>
/// - Returns: <#description#>
public func addNotification(_ observer: Any, selector aSelectorName: Selector, name aName: String, object anObject: Any?) {
    PQNotification.addObserver(observer, selector: aSelectorName, name: NSNotification.Name(rawValue: aName), object: anObject)
}

/// 发送通知
/// - Parameter aName: <#aName description#>
/// - Returns: <#description#>
public func postNotification(name aName: String, userInfo: [AnyHashable: Any]? = nil) {
    PQNotification.post(name: NSNotification.Name(aName), object: nil, userInfo: userInfo)
}

/// 获取是否打开推送
/// - Parameter completeHander: <#completeHander description#>
/// - Returns: <#description#>
public func pushNotificationIsOpen(completeHander: ((_ isOpen: Bool) -> Void)?) {
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().getNotificationSettings { setttings in
            completeHander!(setttings.authorizationStatus == .authorized)
        }
    } else {
        completeHander!(UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false)
    }
}

/// 发送上传本地推送
/// - Parameter isSuccess: 是否上传成功
/// - Returns: <#description#>
public func sendUploadNotification(isSuccess: Bool) {
    let title: String = isSuccess ? "上传完成了！" : "上传失败了！"
    let body: String = isSuccess ? "请点击发布，完成上传。否则，您的视频可能丢失" : "快来看看怎么了？"
    sendLocalNotification(title: title, body: body)
}

/// 发送本地推送
/// - Parameters:
///   - title: 标题
///   - body: 内容
/// - Returns: <#description#>
public func sendLocalNotification(title: String, body: String) {
    // 设置推送内容
    if #available(iOS 10.0, *) {
        let content = UNMutableNotificationContent()
        content.title = title
        content.body = body
        content.badge = 1
        // 设置通知触发器
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
        // 设置请求标识符
        let requestIdentifier = getUniqueId(desc: "notification\(title)")
        // 设置一个通知请求
        let request = UNNotificationRequest(identifier: requestIdentifier,

                                            content: content, trigger: trigger)
        // 将通知请求添加到发送中心
        UNUserNotificationCenter.current().add(request) { error in
            if error == nil {
                print("Time Interval Notification scheduled: \(requestIdentifier)")
            }
        }
    } else {
        // Fallback on earlier versions
        let notification = UILocalNotification()
        notification.alertBody = body
        notification.alertTitle = title
        notification.applicationIconBadgeNumber = 1
        notification.fireDate = Date(timeIntervalSinceNow: 0)
        UIApplication.shared.scheduledLocalNotifications = [notification]
    }
}

/// 打开应用设置
public func openAppSetting() {
    if UIApplication.shared.canOpenURL(URL(string: UIApplication.openSettingsURLString)!) {
        UIApplication.shared.openURL(URL(string: UIApplication.openSettingsURLString)!)
    }
}

/// dns解析
/// - Parameter hostUrl: speed.piaoquantv.com /
/// - Returns: <#description#>
public func parseDNS(hostUrl: String) -> [String: Any]? {
    let host: CFHost? = CFHostCreateWithName(nil, hostUrl as CFString).takeRetainedValue()
    let start = CFAbsoluteTimeGetCurrent()
    var success: DarwinBoolean = false
    var addressList: [String] = Array<String>.init()
    var addresses: NSArray?
    if CFHostStartInfoResolution(host!, .addresses, nil) {
        addresses = (CFHostGetAddressing(host!, &success)?.takeUnretainedValue())
    }
    if success == true {
        for case let theAddress as NSData in addresses! {
            var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
            if getnameinfo(theAddress.bytes.assumingMemoryBound(to: sockaddr.self), socklen_t(theAddress.length),
                           &hostname, socklen_t(hostname.count), nil, 0, NI_NUMERICHOST) == 0
            {
                let numAddress = String(cString: hostname)
                addressList.append("\(hostUrl)/\(numAddress)")
            }
        }
    }
    let end = CFAbsoluteTimeGetCurrent()
    let duration = end - start
    BFLog(message: "duration = \(duration)")
    BFLog(message: "addressList = \(addressList)")
    if addressList.count > 0 {
        return ["dnsResult": arrayToJsonString(addressList), "duration": duration * 1000, "hostName": hostUrl, "networkType": networkStatus()]
    } else {
        return nil
    }
}

/// 获取当前日期
/// - Returns: <#description#>
public func systemCurrentDate() -> String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "YYYY-MM-dd"
    return dateFormatter.string(from: Date())
}

/// 时间戳转日期
/// - Parameter timeInterval: <#timeInterval description#>
/// - Returns: <#description#>
public func timeIntervalToDateString(timeInterval: TimeInterval) -> String {
    let date = Date(timeIntervalSince1970: timeInterval)
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM月dd日 HH:mm"
    return dateFormatter.string(from: date)
}

/// 判断字符串或者字典是否为空
/// - Parameter object: <#object description#>
/// - Returns: <#description#>
public func isEmpty(object: Any?) -> Bool {
    if object == nil {
        return true
    }
    if object is String {
        return (object as! String).count <= 0
    }
    if object is [String: Any] {
        return (object as! [String: Any]).keys.count <= 0
    }
    return false
}

public func isEmptyObject(object: Any?) -> Bool {
    if object == nil {
        return true
    }
    if object is String {
        return object == nil || ((object as? String)?.count ?? 0) <= 0
    }
    if object is [String: Any] {
        return object == nil || ((object as? [String: Any])?.keys.count ?? 0) <= 0
    }
//    if object is List<Object> {
//        return object == nil || ((object as? List<Object>)?.count ?? 0) <= 0
//    }
    return false
}

/// <#Description#>
/// - Parameter string: <#string description#>
/// - Returns: <#description#>
public func isIncludeChineseIn(string: String) -> Bool {
    for (_, value) in string.enumerated() {
        if value >= "\u{4E00}", value <= "\u{9FA5}" {
            return true
        }
    }
    return false
}

/// 获取文件内容的MD5
/// - Parameters:
///   - path: 地址
///   - data: data
/// - Returns: <#description#>
public func contentMD5(path: String? = nil, data _: Data? = nil) -> String? {
    if path == nil || (path?.count ?? 0) <= 0 || !FileManager.default.fileExists(atPath: path ?? "") {
        BFLog(message: "生成内容md5值:地址错误或者不存在\(String(describing: path))")
        return ""
    }
    let att = try? FileManager.default.attributesOfItem(atPath: path ?? "")
    let size = Int64(att?[FileAttributeKey.size] as! UInt64)
    if size <= 0 {
        BFLog(message: "生成内容md5值:文件大小为0\(size)")
        return ""
    }
//    let hash: String = OSSUtil.base64Md5(forFilePath: path)
    let hash: String = ""
    BFLog(message: "生成内容md5值：contentMD5 = \(hash)")
    return hash
}

/// 自适应宽
/// - Parameters:
///   - width: <#width description#>
///   - baseWidth: <#baseWidth description#>
/// - Returns: <#description#>
public func adapterWidth(width: CGFloat, baseWidth: CGFloat = 375) -> CGFloat {
    return width / baseWidth * cScreenWidth
}

/// 自适应高
/// - Parameters:
///   - height: <#height description#>
///   - baseHeight: <#baseHeight description#>
/// - Returns: <#description#>
public func adapterHeight(height: CGFloat, baseHeight: CGFloat = 812) -> CGFloat {
    return height / baseHeight * cScreenHeigth
}

/// 检测URL
/// - Parameter url: <#url description#>
/// - Returns: <#description#>
public func isValidURL(url: String?) -> Bool {
    if url == nil || (url?.count ?? 0) <= 4 || (!(url?.hasPrefix("http") ?? false) && !(url?.hasPrefix("https") ?? false)) {
        return false
    }
    return true
}

/// 相册数据按创建时间排序
public var creaFetchOptions: PHFetchOptions = {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
    return fetchOptions
}()

/// 相册数据按修改时间排序
public var modiFetchOptions: PHFetchOptions = {
    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)]
    return fetchOptions
}()

/// 获取本地素材
public var avAssertOptions: [String: Any]? = {
    [AVURLAssetPreferPreciseDurationAndTimingKey: NSNumber(value: true)]
}()

/// 播放动画图
public var playGifImages: [UIImage] = {
    var gifImages = Array<UIImage>.init()
    for i in 0 ... 44 {
        gifImages.append(UIImage(named: "\(i).png")!)
    }

    return gifImages
}()

/// 压缩图片
/// - Parameter image: <#image description#>
/// -
/// - Returns: <#description#>
public func zipImage(image: UIImage?, size: Int) -> Data? {
    var data = image?.pngData()
    var dataKBytes = Int(data?.count ?? 0) / 1000
    var maxQuality = 0.9
    while dataKBytes > size, maxQuality > 0.01 {
        maxQuality = maxQuality - 0.01
        data = image?.jpegData(compressionQuality: CGFloat(maxQuality))
        dataKBytes = (data?.count ?? 0) / 1000
    }
    return data
}
