
import Foundation
import UIKit
import RNCryptor
import CryptoSwift

extension String {
    func contains(find: String) -> Bool{
        return self.range(of: find) != nil
    }
    func containsIgnoringCase(find: String) -> Bool{
        return self.range(of: find, options: .caseInsensitive) != nil
    }
    var isEmail: Bool {
        let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,20}"
        let emailTest  = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
        return emailTest.evaluate(with: self)
    }
    var isPW: Bool {
        let pwRegEx = "^[a-zA-Z0-9!@.#$%^&*?_~]{4,16}$"
        let pwTest  = NSPredicate(format:"SELF MATCHES %@", pwRegEx)
        return pwTest.evaluate(with: self)
    }
    
    var hangul: String {
        get {
            let hangle = [
                ["ㄱ","ㄲ","ㄴ","ㄷ","ㄸ","ㄹ","ㅁ","ㅂ","ㅃ","ㅅ","ㅆ","ㅇ","ㅈ","ㅉ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"],
                ["ㅏ","ㅐ","ㅑ","ㅒ","ㅓ","ㅔ","ㅕ","ㅖ","ㅗ","ㅘ","ㅙ","ㅚ","ㅛ","ㅜ","ㅝ","ㅞ","ㅟ","ㅠ","ㅡ","ㅢ","ㅣ"],
                ["","ㄱ","ㄲ","ㄳ","ㄴ","ㄵ","ㄶ","ㄷ","ㄹ","ㄺ","ㄻ","ㄼ","ㄽ","ㄾ","ㄿ","ㅀ","ㅁ","ㅂ","ㅄ","ㅅ","ㅆ","ㅇ","ㅈ","ㅊ","ㅋ","ㅌ","ㅍ","ㅎ"]
            ]
            
            return characters.reduce("") { result, char in
                if case let code = Int(String(char).unicodeScalars.reduce(0){$0 + $1.value}) - 44032{
                    if code > -1 && code < 11172{
                        let cho = code / 21 / 28, jung = code % (21 * 28) / 28, jong = code % 28;
                        return result + hangle[0][cho] + hangle[1][jung] + hangle[2][jong]
                    }
                }
                return result + String(char)
            }
        }
    }
    
    var localized: String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: "")
    }
    
    //String Equal 비교
    func isEqualToString(find:String) -> Bool {
        return String(format:self) == find
    }
    
}

extension String {
    var delComma: String {
        let number = Double(self)
        
        let formatter:NumberFormatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.groupingSeparator = ","
        let commoaString = formatter.string(for: number)
        return commoaString ?? "0"
    }
}

extension String {
    func fromDate(format:String) -> Date? {
        let formmater:DateFormatter = {
            let formatter = DateFormatter()
            formatter.locale = Locale.current
            formatter.dateFormat = format
            return formatter
        }()
        return formmater.date(from: self)
    }
}

extension String{
    
    func aesEncrypt() -> String{
        do {
            let iv: Array<UInt8> = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0, 0x00, 0x00, 0x00, 0x00]
            let aes = try AES(key: Array("3c837d501a8f49b1".utf8), blockMode: CBC(iv: iv), padding: .pkcs7)
            let encrypted = try aes.encrypt([UInt8](self.data(using: .utf8)!))
            
//            return encrypted.toHexString()
            return Data(encrypted).base64EncodedString()
        } catch {
            print(error)
        }
        
        return "";
    }
    
//    func aesEncrypt() throws -> String {
//        let encrypted = try AES(key: "3c837d501a8f49b1", iv: "0000000000000000", padding: .pkcs7).encrypt([UInt8](self.data(using: .utf8)!))
//        return Data(encrypted).base64EncodedString()
//    }
    
//    func aesEncrypt(key: String = "3c837d501a8f49b1", iv: String = "0000000000000000") -> String {
//        if let data = self.data(using: String.Encoding.utf8) {
//            do {
//
//                let enc: Array<UInt8> = try AES(key: Array(key.utf8), blockMode: CBC(iv: Array(iv.utf8)), padding: .pkcs7).encrypt(data.bytes)
////                let enc = try AES(key: key, iv: iv, padding: .pkcs7).encrypt(data.bytes)
//                let encData = Data(bytes: enc, count: Int(enc.count))
//                let base64String: String = encData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0));
////                let base64String: String = encData.base64EncodedString()
//                return base64String
//            }
//            catch let error {
//                print(error.localizedDescription)
//                return ""
//            }
//        }
//        return ""
//    }
    
    func encryptWithKey(key:String) -> String? {
        guard let data = self.data(using: .utf8) else{ return nil }
        let encData = RNCryptor.encrypt(data: data, withPassword: key)
        return encData.base64EncodedString()
    }
    
    func decryptWithKey(key:String) -> String? {
        guard let data = Data(base64Encoded: self) else{ return nil }
        do{
            let decData = try RNCryptor.decrypt(data: data, withPassword: key)
            return String(data: decData, encoding: .utf8)
        }catch{
            print(error)
        }
        
        return nil
    }
}

extension String {
    subscript(value: NSRange) -> Substring {
        return self[value.lowerBound..<value.upperBound]
    }
}

extension String {
    subscript(value: CountableClosedRange<Int>) -> Substring {
        get {
            return self[index(at: value.lowerBound)...index(at: value.upperBound)]
        }
    }
    
    subscript(value: CountableRange<Int>) -> Substring {
        get {
            return self[index(at: value.lowerBound)..<index(at: value.upperBound)]
        }
    }
    
    subscript(value: PartialRangeUpTo<Int>) -> Substring {
        get {
            return self[..<index(at: value.upperBound)]
        }
    }
    
    subscript(value: PartialRangeThrough<Int>) -> Substring {
        get {
            return self[...index(at: value.upperBound)]
        }
    }
    
    subscript(value: PartialRangeFrom<Int>) -> Substring {
        get {
            return self[index(at: value.lowerBound)...]
        }
    }
    
    func index(at offset: Int) -> String.Index {
        return index(startIndex, offsetBy: offset)
    }
}

