 import Judo
 
 
+
 public extension String {
+    
+    
+    func cardPresentationString() -> String? {
+        var strippedSelf = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
+
+        if strippedSelf.characters.count == 0 || strippedSelf.cardNetwork() == .Unknown {
+            return nil
+        }
+        
+        var batchesArray = Array<String>()
+        
+        switch self.cardNetwork() {
+        case .Visa(.Debit), .Visa(.Credit), .Visa(.Unknown), .MasterCard(.Debit), .MasterCard(.Credit), .MasterCard(.Unknown), .Dankort, .JCB, .InstaPayment, .Discover where strippedSelf.characters.count == 16:
+            repeat {
+                let batch = strippedSelf.substringToIndex(advance(strippedSelf.startIndex, 4))
+                batchesArray.append(batch)
+                strippedSelf = strippedSelf.substringFromIndex(advance(strippedSelf.startIndex, 4))
+            } while strippedSelf.characters.count > 0
+            break
+        case .AMEX:
+            
+            break
+        default:
+            batchesArray.append(strippedSelf)
+        }
+        
+        var resultString = batchesArray.first
+        for batch in batchesArray.dropFirst() {
+            resultString = "\(resultString) \(batch)"
+        }
+        return resultString
+        
+    }
+    
     
     /**
     see https://en.wikipedia.org/wiki/Bank_card_number

        // Card Networks with multiple different prefix
        // AMEX begins with 34 & 37
        for prefix in ["34", "37"] {
            if self.beginsWith(prefix) {
                return .AMEX
            }
        }
        
        // MasterCard begins with 51 - 55
        for prefix in (51...55).map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .MasterCard(.Unknown)
            }
        }
        
        // future MasterCard range 2221-2720
        for prefix in (2221...2720).map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .MasterCard(.Unknown)
            }
        }
        
        // Maestro has 50, 56-69
        for prefix in [56...69].map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .Maestro
            }
        }
        
        // Diners Club 300-305 / 309 & 36, 38, 39
        for prefix in (300...305).map({ String($0) }) + ["36", "38", "39", "309"] {
            if self.beginsWith(prefix) {
                return .DinersClub
            }
        }
        
        // Discover 644-649
        for prefix in (644...649).map({ String($0) }) + ["65", "6011"] + (622126...622925).map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .Discover
            }
        }
        
        // InstaPayment
        for prefix in (637...639).map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .InstaPayment
            }
        }
        
        // JCB 3528-3589
        for prefix in (3528...3589).map({ String($0) }) {
            if self.beginsWith(prefix) {
                return .JCB
            }
        }

    */
    func cardNetwork() -> CardNetwork {
        
        let strippedSelf = self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
        
        // Card Networks that only have one prefix
        switch self {
        case _ where strippedSelf.beginsWith("1"):
            return .UATP
        case _ where strippedSelf.beginsWith("4"):
            return .Visa(.Unknown)
        case _ where strippedSelf.beginsWith("62"):
            return .ChinaUnionPay
        case _ where strippedSelf.beginsWith("636"):
            return .InterPayment
        case _ where strippedSelf.beginsWith("5019"):
            return .Dankort
        default:
            break
