// // InstancesDataManager.swift // elpha-ios // // Created by Dwayne Harris on 9/18/18. // Copyright © 2018 Elpha. All rights reserved. // import Alamofire import CoreData import UIKit class InstancesDataManager { static let shared = InstancesDataManager() let fetchLimit = 20 var instances: [ISInstanceMO] = [] var nextID: String? var finished = false func upsertLanguage(string: String) -> ISLanguageMO? { let context = CoreDataManager.shared.context context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy let request = NSFetchRequest(entityName: "ISLanguage") request.predicate = NSPredicate(format: "id == %@", string) do { let results = try context.fetch(request) if let language = results.first { return language } else { let language = ISLanguageMO(context: context) language.id = string return language } } catch { print("\(error)") return nil } } func upsertCategory(string: String) -> ISCategoryMO? { let context = CoreDataManager.shared.context context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy let request = NSFetchRequest(entityName: "ISCategory") request.predicate = NSPredicate(format: "id == %@", string) do { let results = try context.fetch(request) if let category = results.first { return category } else { let category = ISCategoryMO(context: context) category.id = string return category } } catch { print("\(error)") return nil } } func setAttributes(on instance: ISInstanceMO, with attributes: [String: Any]) { guard let id = attributes["id"] as? String, let name = attributes["name"] as? String else { return } let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" dateFormatter.locale = Locale(identifier: "en_US_POSIX") instance.id = id instance.name = name instance.url = URL(string: "https://\(name)")! instance.uptime = attributes["uptime"] as! Int32 instance.up = attributes["up"] as! Bool instance.dead = attributes["dead"] as! Bool instance.version = attributes["version"] as? String instance.ipv6 = attributes["ipv6"] as! Bool instance.users = Int64(attributes["users"] as! String)! instance.statuses = Int64(attributes["statuses"] as! String)! instance.connections = Int64(attributes["connections"] as! String)! instance.openRegistrations = attributes["open_registrations"] as! Bool instance.fetchedAt = Date() if let activeUsers = attributes["active_users"] as? Int64 { instance.activeUsers = activeUsers } if let updatedAt = attributes["updated_at"] as? String { instance.updatedAt = dateFormatter.date(from: updatedAt) } if let checkedAt = attributes["checked_at"] as? String { instance.checkedAt = dateFormatter.date(from: checkedAt) } if let thumbnail = attributes["thumbnail"] as? String { instance.thumbnail = URL(string: thumbnail)! } if let info = attributes["info"] as? [String: Any] { instance.shortDesc = info["short_description"] as? String instance.fullDescription = info["full_description"] as? String instance.topic = info["topic"] as? String for language in info["languages"] as! [String] { if let l = upsertLanguage(string: language) { instance.mutableSetValue(forKey: "languages").add(l) } } for category in info["categories"] as! [String] { if let c = upsertCategory(string: category) { instance.mutableSetValue(forKey: "categories").add(c) } } } } func clearInstances() { let request = NSFetchRequest(entityName: "ISInstance") do { let instances = try CoreDataManager.shared.context.fetch(request) instances.forEach { instance in CoreDataManager.shared.context.delete(instance) } } catch { print("\(error)") } } func reloadInstances(completion: @escaping (Error?) -> Void) { nextID = nil finished = false loadInstances(completion: completion) } func loadInstances(completion: @escaping (Error?) -> Void) { var params = [ "count=\(fetchLimit)", "sort_by=users", "sort_order=desc", "include_closed=true", "include_down=false", ] if let nextID = nextID { params.append("min_id=\(nextID)") } let requestURL = "\(Config.instancesServiceURL)\(Config.instancesServiceListEndpoint)?\(params.joined(separator: "&"))" let headers: HTTPHeaders = ["Authorization": "Bearer \(Config.instancesServiceSecret)"] Alamofire.request(requestURL, headers: headers).validate().responseJSON { response in switch response.result { case .success(let value): guard let result = value as? [String: Any], let pagination = result["pagination"] as? [String: Any], let instances = result["instances"] as? [Any] else { completion(NSError()) return } if let nextID = pagination["next_id"] as? String { self.nextID = nextID } else { self.nextID = nil self.finished = true } do { for case let instance as [String: Any] in instances { if let id = instance["id"] as? String { let request = NSFetchRequest(entityName: "ISInstance") request.predicate = NSPredicate(format: "id == %@", id) let results: [ISInstanceMO] = try CoreDataManager.shared.context.fetch(request) if let i = results.first { self.setAttributes(on: i, with: instance) } else { let i = ISInstanceMO(context: CoreDataManager.shared.context) self.setAttributes(on: i, with: instance) } } } CoreDataManager.shared.saveContext() completion(nil) } catch { completion(error) return } case .failure(let error): completion(error) } } } }