//
//  String+Ext.swift
//  PQSpeed
//
//  Created by SanW on 2020/7/22.
//  Copyright © 2020 BytesFlow. All rights reserved.
//

import CommonCrypto
import Foundation
import MobileCoreServices

public extension String {
    /// md5加密
    var md5: String {
        let str = cString(using: String.Encoding.utf8)
        let strLen = CUnsignedInt(lengthOfBytes(using: String.Encoding.utf8))
        let digestLen = Int(CC_MD5_DIGEST_LENGTH)
        let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen)
        CC_MD5(str!, strLen, result)
        let hash = NSMutableString()
        for i in 0 ..< digestLen {
            hash.appendFormat("%02x", result[i])
        }
        result.deallocate()
        return hash as String
    }

    // 文件后缀名
    var pathExtension: String {
        return (self as NSString).pathExtension
    }

    func ga_widthForComment(font: UIFont, height: CGFloat = 15) -> CGFloat {
        let rect = NSString(string: self).boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: height), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(rect.width)
    }

//
//    public  func ga_heightForComment(fontSize: CGFloat, width: CGFloat) -> CGFloat {
//        let font = UIFont.systemFont(ofSize: fontSize)
//        let rect = NSString(string: self).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
//        return ceil(rect.height)
//    }
//
//    public  func ga_heightForComment(fontSize: CGFloat, width: CGFloat, maxHeight: CGFloat) -> CGFloat {
//        let font = UIFont.systemFont(ofSize: fontSize)
//        let rect = NSString(string: self).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
//        return ceil(rect.height)>maxHeight ? maxHeight : ceil(rect.height)
//    }

    func enumerateSearchText(searchText: String?, complate: (_ idx: Int, _ range: NSRange) -> Void) {
        if searchText == nil || (searchText?.count ?? 0) <= 0 || !contains(searchText!) {
            return
        }
        let len: Int = searchText!.count
        var loc: Int = 0
        let subStrings: [String] = NSString(string: self).components(separatedBy: searchText!)
        for (idx, subText) in subStrings.enumerated() {
            loc = loc + subText.count
            let range = NSRange(location: loc, length: len)
            complate(idx, range)
            loc = loc + len
            if idx == subStrings.count - 2 {
                break
            }
        }
    }

    func attributedTextWithSearchText(searchText: String?, textColor: UIColor, textFont: UIFont, searchTextColor: UIColor, searchTextFont: UIFont) -> NSMutableAttributedString {
        let attbText = NSMutableAttributedString(string: self, attributes: [NSAttributedString.Key.font: textFont, NSAttributedString.Key.foregroundColor: textColor])
        if count <= 0 || searchText == nil || (searchText?.count ?? 0) <= 0 {
            return attbText
        }
        for tempStr in searchText! {
            enumerateSearchText(searchText: "\(tempStr)") { _, range in
                attbText.setAttributes([NSAttributedString.Key.font: searchTextFont, NSAttributedString.Key.foregroundColor: searchTextColor], range: range)
            }
        }
        return attbText
    }

    // 判断是否为空
    var isSpace: Bool {
        return allSatisfy { $0.isWhitespace }
    }

    /// 通过 文件路径/文件名/文件后缀 获取mimeType(文件媒体类型)
    /// - Parameter pathExtension: <#pathExtension description#>
    /// - Returns: <#description#>
    func mimeType() -> String {
        if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (self as NSString).pathExtension as CFString, nil)?.takeRetainedValue() {
            if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?
                .takeRetainedValue()
            {
                return mimetype as String
            }
        }
        return "application/octet-stream"
    }

    // 将原始的url编码为合法的url
    func urlEncoded() -> String {
        let encodeUrlString = addingPercentEncoding(withAllowedCharacters:
            .urlQueryAllowed)
        return encodeUrlString ?? ""
    }

    // 将编码后的url转换回原始的url
    func urlDecoded() -> String {
        return removingPercentEncoding ?? ""
    }

    // 判断是否包含Emoji表情
    func isEmoji() -> Bool {
        let numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
        guard !numbers.contains(self) else {
            return false
        }
        let tempEmoji: [Unicode.Scalar] = ["\u{26F8}", "\u{26F7}", "\u{263A}", "\u{2639}", "\u{2620}", "\u{270C}", "\u{261D}", "\u{0001F441}", "\u{0001F5E3}", "\u{0001F575}", "\u{0001F574}", "\u{26D1}", "\u{0001F576}", "\u{0001F577}", "\u{0001F54A}", "\u{0001F43F}", "\u{2618}", "\u{0001F32A}", "\u{2600}", "\u{0001F324}", "\u{0001F325}", "\u{2601}", "\u{0001F326}", "\u{0001F327}", "\u{26C8}", "\u{0001F329}", "\u{0001F328}", "\u{2744}", "\u{2603}", "\u{0001F32C}", "\u{2602}", "\u{0001F32B}", "\u{0001F336}", "\u{0001F37D}"]
        let scalars = unicodeScalars.map { $0.value }
        for element in scalars {
            if let scalar = Unicode.Scalar(element) {
                if #available(iOS 10.2, *) {
                    if (scalar.properties.isEmoji && scalar.properties.isEmojiPresentation) || tempEmoji.contains(scalar) {
                        return true
                    } else {
                        BFLog(message: "是表情==\(element),\(scalar)")
                    }
                }
            }
        }
        return false
    }

    internal var isContainsEmoji: Bool {
        for scalar in unicodeScalars {
            switch scalar.value {
            case 0x1F600 ... 0x1F64F, // Emoticons
                 0x1F300 ... 0x1F5FF, // Misc Symbols and Pictographs
                 0x1F680 ... 0x1F6FF, // Transport and Map
                 0x2600 ... 0x26FF, // Misc symbols
                 0x2700 ... 0x27BF, // Dingbats
                 0xFE00 ... 0xFE0F: // Variation Selectors
                return true
            default:
                continue
            }
        }
        return false
    }

    // 是否包含表情
    internal var containsEmoji: Bool {
        for scalar in unicodeScalars {
            switch scalar.value {
            case
                0x00A0 ... 0x00AF,
                0x2030 ... 0x204F,
                0x2120 ... 0x213F,
                0x2190 ... 0x21AF,
                0x2310 ... 0x329F,
                0x1F000 ... 0x1F9CF:
                return true
            default:
                continue
            }
        }
        return false
    }

    /**
     * 字母、数字、中文正则判断（不包括空格）
     *注意: 因为考虑到输入习惯,许多人习惯使用九宫格,这里在正常选择全键盘输入错误的时候,进行九宫格判断,九宫格对应的是下面➋➌➍➎➏➐➑➒的字符
     */
    internal static func isInputRuleNotBlank(str: String) -> Bool {
        let pattern = "^[a-zA-Z\\u4E00-\\u9FA5\\d]*$"
        let pred = NSPredicate(format: "SELF MATCHES %@", pattern)
        let isMatch = pred.evaluate(with: str)
        if !isMatch {
            let other = "➋➌➍➎➏➐➑➒"
            let len = str.count
            for i in 0 ..< len {
                let tmpStr = str as NSString
                let tmpOther = other as NSString
                let c = tmpStr.character(at: i)

                if !(isalpha(Int32(c)) > 0 || isalnum(Int32(c)) > 0 || (Int(c) == "_".hashValue) || (Int(c) == "-".hashValue) || (c >= 0x4E00 && c <= 0x9FA6) || (tmpOther.range(of: str).location != NSNotFound)) {
                    return false
                }
                return true
            }
        }
        return isMatch
    }
}

public extension Optional where Wrapped == String {
    var isSpace: Bool {
        return self?.isSpace ?? true
    }
}
