<commit_before>//
//  CombinedURLItemSyncingController.swift
//  Hipstapaper
//
//  Created by <NAME> on 11/26/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

open class CombinedURLItemSyncingController: DoubleSourcePersistenceType {
    
    private let realmController: SingleSourcePersistenceType = RealmURLItemSyncingController()
    private let cloudKitController: SingleSourcePersistenceType = CloudKitURLItemSyncingController()
    
    public var ids: Set<String> {
        return self.realmController.ids
    }
    
    public init() {}
    
    // ugh this is pretty bad pyramid of doom
    // it basically just calls back the completion handlers on error
    // if there is success it keeps going forward with the syncing process
    public func sync(quickResult: SuccessResult?, fullResult: SuccessResult?) {
        self.realmController.reloadData() { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)

            switch realmResult {
            case .error:
                // if realm errors, also call fullResult with the realmError
                fullResult?(realmResult)
            case .success:
                // if realm is successful, continue to cloud controller
                self.cloudKitController.reloadData() { cloudResult in
                    switch cloudResult {
                    case .error:
                        // if cloud errors, call fullResult with the cloudError
                        fullResult?(cloudResult)
                    case .success:
                        // now the cloud sync and the realm sync were both successful, time to sync
                        let syncer = RealmCloudKitSyncer(realmController: self.realmController, cloudKitController: self.cloudKitController)
                        // call to sync with the full completion handler
                        syncer.sync() { syncResult in
                            switch syncResult {
                            case .error:
                                // if there is an error syncing, call back
                                fullResult?(.success())
                            case .success(let changes):
                                // if we are successful, we need to know if there are changes
                                switch changes {
                                case .noChanges:
                                    // if there are no changes, call back
                                    fullResult?(.success())
                                case .changes:
                                    // if there are changes, recurse
                                    self.sync(quickResult: .none, fullResult: fullResult)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    public func createItem(withID id: String?, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.createItem(withID: id) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success(let realmValue):
                // if realm is successful, continue to cloud controller
                self.cloudKitController.createItem(withID: realmValue.cloudKitID) { cloudCreateResult in
                    switch cloudCreateResult {
                    case .success(var cloudValue):
                        cloudValue.realmID = realmValue.realmID
                        fullResult?(.success(cloudValue))
                    case .error:
                        fullResult?(cloudCreateResult)
                    }
                }
            }
        }
    }
    
    public func readItem(withID id: String, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.readItem(withID: id) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .success:
                // if realm succeeds, just finish
                fullResult?(realmResult)
            case .error:
                // if realm errors, try getting the value from the cloud
                self.cloudKitController.readItem(withID: id, result: fullResult)
            }
            
        }
    }
    
    public func update(item: URLItemType, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.update(item: item) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success(let updatedItem):
                // if realm is successful, continue to cloud controller
                self.cloudKitController.update(item: updatedItem, result: fullResult)
            }
        }
    }
    
    public func delete(item: URLItemType, quickResult: SuccessResult?, fullResult: SuccessResult?) {
        self.realmController.delete(item: item) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success:
                // if realm is successful, continue to cloud controller
                self.cloudKitController.delete(item: item, result: fullResult)
            }
        }
    }
}<commit_msg>added realmID correction on pure cloudItems<commit_after>//
//  CombinedURLItemSyncingController.swift
//  Hipstapaper
//
//  Created by <NAME> on 11/26/16.
//  Copyright © 2016 <NAME>. All rights reserved.
//

open class CombinedURLItemSyncingController: DoubleSourcePersistenceType {
    
    private let realmController: SingleSourcePersistenceType = RealmURLItemSyncingController()
    private let cloudKitController: SingleSourcePersistenceType = CloudKitURLItemSyncingController()
    
    public var ids: Set<String> {
        return self.realmController.ids
    }
    
    public init() {}
    
    // ugh this is pretty bad pyramid of doom
    // it basically just calls back the completion handlers on error
    // if there is success it keeps going forward with the syncing process
    public func sync(quickResult: SuccessResult?, fullResult: SuccessResult?) {
        self.realmController.reloadData() { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)

            switch realmResult {
            case .error:
                // if realm errors, also call fullResult with the realmError
                fullResult?(realmResult)
            case .success:
                // if realm is successful, continue to cloud controller
                self.cloudKitController.reloadData() { cloudResult in
                    switch cloudResult {
                    case .error:
                        // if cloud errors, call fullResult with the cloudError
                        fullResult?(cloudResult)
                    case .success:
                        // now the cloud sync and the realm sync were both successful, time to sync
                        let syncer = RealmCloudKitSyncer(realmController: self.realmController, cloudKitController: self.cloudKitController)
                        // call to sync with the full completion handler
                        syncer.sync() { syncResult in
                            switch syncResult {
                            case .error:
                                // if there is an error syncing, call back
                                fullResult?(.success())
                            case .success(let changes):
                                // if we are successful, we need to know if there are changes
                                switch changes {
                                case .noChanges:
                                    // if there are no changes, call back
                                    fullResult?(.success())
                                case .changes:
                                    // if there are changes, recurse
                                    self.sync(quickResult: .none, fullResult: fullResult)
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    public func createItem(withID id: String?, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.createItem(withID: id) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success(let realmValue):
                // if realm is successful, continue to cloud controller
                self.cloudKitController.createItem(withID: realmValue.cloudKitID) { cloudCreateResult in
                    let updatedResult = type(of: self).update(cloudItemResult: cloudCreateResult, withRealmItemID: realmValue.realmID)
                    fullResult?(updatedResult)
                }
            }
        }
    }
    
    public func readItem(withID id: String, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.readItem(withID: id) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .success:
                // if realm succeeds, just finish
                fullResult?(realmResult)
            case .error:
                // if realm errors, try getting the value from the cloud
                self.cloudKitController.readItem(withID: id) { cloudReadResult in
                    let updatedResult = type(of: self).update(cloudItemResult: cloudReadResult, withRealmItemID: id)
                    fullResult?(updatedResult)
                }
            }
            
        }
    }
    
    public func update(item: URLItemType, quickResult: URLItemResult?, fullResult: URLItemResult?) {
        self.realmController.update(item: item) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success(let updatedItem):
                // if realm is successful, continue to cloud controller
                self.cloudKitController.update(item: updatedItem) { cloudUpdateResult in
                    let updatedResult = type(of: self).update(cloudItemResult: cloudUpdateResult, withRealmItemID: item.realmID)
                    fullResult?(updatedResult)
                }
            }
        }
    }
    
    public func delete(item: URLItemType, quickResult: SuccessResult?, fullResult: SuccessResult?) {
        self.realmController.delete(item: item) { realmResult in
            // always call the quick result with the results of realm
            quickResult?(realmResult)
            
            switch realmResult {
            case .error:
                // if realm errors, call fullResult with the realmError
                fullResult?(realmResult)
            case .success:
                // if realm is successful, continue to cloud controller
                self.cloudKitController.delete(item: item, result: fullResult)
            }
        }
    }
    
    private class func update(cloudItemResult: Result<URLItemType>, withRealmItemID realmID: String) -> Result<URLItemType> {
        // since cloud results don't have a real realm ID, we need to add the realm realm ID before returning it to the app
        switch cloudItemResult {
        case .success(var cloudItem):
            cloudItem.realmID = realmID
            return .success(cloudItem)
        case .error:
            return cloudItemResult
        }
    }
}
{'fraction_non_alphanumeric': 0.06299274061353524, 'fraction_numerical': 0.001561158379517602, 'mean_word_length': 1.4853540252182347, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7397622', 'n_tokens_mistral': 2922, 'n_tokens_neox': 2810, 'n_words': 913}