//
//  Digest.swift
//  PaiAi
//
//  Created by LISA on 2017/6/1.
//  Copyright © 2017年 yb. All rights reserved.
//

import UIKit


enum EncryptionAlgorithm: CC_LONG {
//    case md2 = 16
//    case md4 = 17
    case md5 = 16
    case sha1 = 20
    case sha224 = 28
    case sha256 = 32
    case sha384 = 48
    case sha512 = 64
    
}

extension Data{
    public var bytes:UnsafePointer<UInt8>{
        return self.withUnsafeBytes({ (pointer:UnsafePointer<UInt8>) -> UnsafePointer<UInt8> in
            return pointer
        })
    }
}

//MARK:md and sha
extension Data {
    
    fileprivate func digestAlgorithm(algorithm : EncryptionAlgorithm) ->UnsafeMutablePointer<CUnsignedChar>{
        let strlen = CC_LONG(16)
        switch algorithm {
//        case .md2:
//            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_MD2_DIGEST_LENGTH))
//            CC_MD2(self.bytes, strlen, digest)
//            return digest
//        case .md4:
//            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_MD4_DIGEST_LENGTH))
//            CC_MD4(self.bytes, strlen, digest)
//            return digest
        case .md5:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_MD5_DIGEST_LENGTH))
            CC_MD5(self.bytes, strlen, digest)
            return digest
        case .sha1:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_SHA1_DIGEST_LENGTH))
            CC_SHA1(self.bytes, strlen, digest)
            return digest
        case .sha224:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_SHA224_DIGEST_LENGTH))
            CC_SHA224(self.bytes, strlen, digest)
            return digest
        case .sha256:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_SHA256_DIGEST_LENGTH))
            CC_SHA256(self.bytes, strlen, digest)
            return digest
        case .sha384:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_SHA384_DIGEST_LENGTH))
            CC_SHA384(self.bytes, strlen, digest)
            return digest
        case .sha512:
            let digest = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: Int(CC_SHA512_DIGEST_LENGTH))
            CC_SHA512(self.bytes, strlen, digest)
            return digest
        }
    }
    
    //return the string
    func digestString(algorithm : EncryptionAlgorithm) -> String{
        let length = algorithm.rawValue
        let digest = digestAlgorithm(algorithm: algorithm)
        
        var outStr = ""
        for i in 0..<Int(length) {
            outStr = outStr.appendingFormat("%02x", digest[i])
        }
        return outStr.uppercased()
    }
    //return the data
    func digestData(algorithm : EncryptionAlgorithm) -> Data {
        let str = digestString(algorithm: algorithm)
        return str.data(using: String.Encoding.utf8)!
    }
    
    func digestBase64Data(algorithm : EncryptionAlgorithm) -> Data {
        return digestData(algorithm: algorithm).base64EncodedData()
    }
    
    func digestBase64String(algorithm : EncryptionAlgorithm) -> String {
        return digestData(algorithm: algorithm).base64EncodedString()
    }
}

extension String {
    //return the stringx
    func digestString(algorithm : EncryptionAlgorithm) -> String{
        return self.myData.digestString(algorithm: algorithm)
    }
    //return the data
    func digestData(algorithm : EncryptionAlgorithm) -> Data {
        return self.myData.digestData(algorithm: algorithm)
    }
    
    func digestBase64Data(algorithm : EncryptionAlgorithm) -> Data {
        return self.myData.digestBase64Data(algorithm: algorithm)
    }
    
    func digestBase64String(algorithm : EncryptionAlgorithm) -> String {
        return self.myData.digestBase64String(algorithm: algorithm)
        
    }
}