Proyectos de Subversion Iphone Microlearning - Inconcert

Rev

Rev 19 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

//
//  SyncAdapter.swift
//  twogetskills
//
//  Created by Efrain Yanez Recanatini on 2/24/22.
//

import Foundation

import Foundation
import Alamofire
import SwiftyJSON
import SwiftUI
import TTGSnackbar

class SyncAdapter
{
    private var appData = Environment(\.appData).wrappedValue
    
    private let syncDao : SyncDao = SyncDao()
    private var inProgress = false;

    
    @objc func updateTimerForeground() {
        if inProgress   {
            return
        }
        

        
        inProgress = true
        let myQue = DispatchQueue(label: "syncQuueForeground")
        myQue.async {
            
            if self.isCheckChangesRequired()  {
                self.checkChanges(isForeground:true) { success in
                    self.inProgress = false;
                }
            } else {
                self.sync(isForeground: true) { success in
                    self.inProgress = false;
                }
            }
        }
    }
    

    
     func isCheckChangesRequired() -> Bool {
        if !appData.userUuid.isEmpty && !appData.maxDateChanges.isEmpty {

            
            let formatterService = DateFormatter()
            formatterService.dateFormat = Constants.FORMAT_DATETIME_SERVICE
            guard let lastCheckChanges = formatterService.date(from: appData.lastCheckChanges) else {
                let now = Date()
                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
                let dateOn = dateFormatter.string(from: now)
                
                appData.lastCheckChanges = dateOn
                appData.save()
                
                return false
                
            }
            
            
            let now = Date()
          
            
            let diffComponents = Calendar.current.dateComponents([.minute], from: lastCheckChanges, to: now)
            let minutes = diffComponents.minute!
            
            
            return minutes > Constants.SYNC_CHECK_CHANGES_PERIOD
            
        }
        
        return false
    }
    
    func checkChanges(isForeground : Bool,  completionHandler : @escaping (_ success : Bool) -> Void) {
        
        
        
        
        if syncDao.countPendingRecords() > 0 {
            completionHandler(true)
        }
        
        
        var parameters = [String : String]()
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_APPLICATION_ID] = "\(Config.APPLICATION_ID)"
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_VARIANT_ID] = "\(Config.VARIANT_ID)"
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_DEVICE_UUID] = appData.deviceUuid
        
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_MAX_DATE_CHANGES] = appData.maxDateChanges
        
        
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_IS_FOREGROUND] = isForeground ? "1" : "0"
        

        
        
        let capsuleDao = CapsuleDao()
        let capsules : [CapsuleModel] = capsuleDao.selectAll()
        
        parameters[Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_MAX_IDS] = String(capsules.count)
        
        var i : Int = 0
        while i < capsules.count {
     
            parameters["\(Constants.POST_MICROLEARNING_CHECK_CHANGES_FIELD_ID)\(i+1)"] = "\(capsules[i].topicUuid)" + "|" + "\(capsules[i].uuid)"
            
            i += 1
        }
        
       // print(parameters)
        
        let headerSecurity : HeaderSecurity = HeaderSecurity()
        
        let headers: HTTPHeaders = [
            .init(name: Constants.HTTP_HEADER_SECURITY_TOKEN, value: appData.deviceUuid),
            .init(name: Constants.HTTP_HEADER_SECURITY_SECRET, value: headerSecurity.secret),
            .init(name: Constants.HTTP_HEADER_SECURITY_CREATED, value: String(headerSecurity.created)),
            .init(name: Constants.HTTP_HEADER_SECURITY_RAND, value: String(headerSecurity.rand)),
            .accept(Constants.HTTP_HEADER_ACCEPT)
        ]
        
        AF.request(Config.URL_CHECK_CHANGES, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in

            switch response.result {
                case .success:
                    let result = try? JSON(data: response.data!)
                    if result?["success"] ?? "" != false{
                        
    
                        
                        if result?["data"] ?? "" != "" {
                            let now = Date()
                            let dateFormatter = DateFormatter()
                            dateFormatter.dateFormat = Constants.FORMAT_DATETIME_SERVICE
                            let dateOn = dateFormatter.string(from: now)
                            
                            let max_date_changes = result!["data"]["max_date_changes"].string ?? ""
                            let snew_capsules =  result!["data"]["new_capsules"].string ?? ""
                            
                            
                            let new_capsules = Int(snew_capsules) ?? 0
                            
                            
                            var processChanges = new_capsules > 0
                            processChanges = processChanges || self.appData.maxDateChanges != max_date_changes
                            
                            if processChanges {
                                self.appData.maxDateChanges = max_date_changes
                            }
                            
                            self.appData.lastCheckChanges = dateOn
                            self.appData.save()
                            
                            if new_capsules > 0  {
                                let userinfo = ["new_capsules" : String(new_capsules), "is_foreground" : (isForeground ? "1" : "0")]
                                
                                NotificationCenter.default.post(name: Constants.NOTIFICATION_NAME_COMMAND_REFRESH_CONTENT , object: self, userInfo: userinfo)
                            }
                            
                            
                            
                            if result?["data"]["rating_and_comments"]  ?? "" != ""  {
                                let capsuleDao = CapsuleDao()
                                var capsuleModel : CapsuleModel
                                
                                for ratingAndComment in result!["data"]["rating_and_comments"] {
                                    
                                    let uuid = ratingAndComment.1["uuid"].string ?? ""
                                    let total_comments = Int(ratingAndComment.1["total_comments"].string ?? "0") ?? 0
                                    let total_rating = Decimal(Double(ratingAndComment.1["total_rating"].string ?? "0") ?? 0)
                                    
        
                                    if !uuid.isEmpty {
                                        capsuleModel = capsuleDao.selectByUuid(uuid: uuid)
                                        capsuleModel.totalRating = total_rating
                                        capsuleModel.totalComments = total_comments
                                        capsuleDao.update(capsule: capsuleModel)
                                    }
                                }
                            }
                        }
                    }
                break
                case .failure:
                   // print("JSON = \(String(describing: Error.self))")
                    
                    
                break
            }

        }
    

        completionHandler(true)
    }
    
    
    
    func sync(isForeground : Bool, completionHandler : @escaping (_ success : Bool) -> Void) {

        let recordsSync = syncDao.selectBatch()
        
        //print(recordsSync)
        
        if recordsSync.count > 0 {
            var availableForOtherOperation = true;
            for recordSync in recordsSync
            {
                if recordSync.type == Constants.SYNC_ADAPTER_TYPE_DEVICE {
                    availableForOtherOperation = false
                    registerDevice(record: recordSync)
                }
                else if availableForOtherOperation && recordSync.type == Constants.SYNC_ADAPTER_TYPE_FCM {
                    availableForOtherOperation = false
                    registerFcm(record: recordSync)
                }
            }
            
            if(availableForOtherOperation) {
                
                var parameters = [ String: String ]()
                var i : Int = 0
                for recordSync in recordsSync
                {
                    if recordSync.type == Constants.SYNC_ADAPTER_TYPE_SYNC {
                        i  += 1
                        let keyData = Constants.POST_SYNC_BATCH_FIELD_RECORD_DATA + String(i);
                        
                        let keySyncId = Constants.POST_SYNC_BATCH_FIELD_RECORD_SYNC_ID + String(i);
                        
                        //print("keyData = \(keyData) keySincId = \(keySyncId)")
                        
                        parameters["\(keyData)"]  = "\(recordSync.data)"
                        
                        parameters["\(keySyncId)"]  =  String(recordSync.id)
                        
                    }
                }
               
                if i > 0 {
                    parameters[Constants.POST_SYNC_BATCH_FIELD_MAX_RECORDS] = "\(i)"
                    parameters[Constants.POST_SYNC_BATCH_FIELD_DEVICE_UUID] = appData.deviceUuid
                    parameters[Constants.POST_SYNC_BATCH_FIELD_APPLICATION_ID] = "\(Config.APPLICATION_ID)"
                    parameters[Constants.POST_SYNC_BATCH_FIELD_VARIANT_ID] = "\(Config.VARIANT_ID)"
                    
                    sendSyncBatch(parameters: parameters)
                }
            }
        }
        

        completionHandler(true)
    }
    
    func sendSyncBatch(parameters : [String : String])
    {
        print("Send Sync Batch  ")
        //print(parameters)
        
        
        let headers: HTTPHeaders = [
            .accept(Constants.HTTP_HEADER_ACCEPT)
        ]
        
        AF.request(Config.URL_SYNC_BATCH, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
            
            
            
            switch response.result {
                case .success:
                    let result = try? JSON(data: response.data!)
                    if result?["success"] ?? "" != false{
                        
                        if result?["data"] != "" {
 
                            for sync in result!["data"] {
                                //let success = sync.1["success"].string ?? ""
                                let sync_id = Int(sync.1["sync_id"].string ?? "0") ?? 0
                                if sync_id > 0 {
                                    self.syncDao.remove(id: sync_id)
                                }
                            }
                        }
                    }
                break
                case .failure:
                   // print("JSON = \(String(describing: Error.self))")
                break
            }
        }
        
        
    }
    
    func sendSync(record: SyncModel)
    {
        let parameters = [
            Constants.POST_SYNC_FIELD_APPLICATION_ID: "\(Config.APPLICATION_ID)",
            Constants.POST_SYNC_FIELD_VARIANT_ID: "\(Config.VARIANT_ID)",
            Constants.POST_SYNC_FIELD_DEVICE_UUID: "\(appData.deviceUuid)",
            Constants.POST_SYNC_FIELD_DATA: "\(record.data)",
            Constants.POST_SYNC_FIELD_SYNC_ID: "\(record.id)"
        ]
        let headers: HTTPHeaders = [
            .accept(Constants.HTTP_HEADER_ACCEPT)
        ]
        
        AF.request(Config.URL_SYNC, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
            
            //print("Send Sync  ")
            
            switch response.result {
                case .success:
                    let result = try? JSON(data: response.data!)
                    if result?["success"] ?? "" != false {
                        
                        
                        
                        
                        let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
                        if sync_id > 0 {
                            self.syncDao.remove(id: sync_id)
                        }
                    }
                break
                case .failure:
                   // print("JSON = \(String(describing: Error.self))")
                break
            }
        }
    }

    func registerFcm(record: SyncModel) {

      
        
        
        let deviceUuid = appData.deviceUuid
        let parameters = [
            Constants.POST_FCM_FIELD_APPLICATION_ID: "\(Config.APPLICATION_ID)",
            Constants.POST_FCM_FIELD_VARIANT_ID: "\(Config.VARIANT_ID)",
            Constants.POST_FCM_FIELD_DEVICE_UUID: "\(deviceUuid)",
            Constants.POST_FCM_FIELD_TOKEN: "\(record.data)",
            Constants.POST_FCM_FIELD_SYNC_ID: "\(record.id)"
        ]
        print("Register FCM parameters: \(parameters)");
        
        let headers: HTTPHeaders = [
            .accept(Constants.HTTP_HEADER_ACCEPT)
        ]
            
        AF.request(Config.URL_FCM, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON{response in
            
            print("Register FCM Request")
            
            switch response.result {
                case .success:
                    let result = try? JSON(data: response.data!)
                    if result?["success"] ?? "" != false {

                        print("Register FCM success = true ")

                        let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
                        if sync_id > 0 {
                            self.syncDao.remove(id: sync_id)
                        }
                    } else {
                        print("Register FCM success = false : \(result?["data"]))")
                    }
                    break
                case .failure:
                    print("Register  FCM failura : \(String(describing: Error.self))")
                    break
            }
        }
    }
    

    func registerDevice(record: SyncModel)
    {
       
        
        
        let version = UIDevice.current.systemVersion
        let model = UIDevice.current.localizedModel

        
        
        let parameters = [
            Constants.POST_DEVICE_FIELD_APPLICATION_ID: "\(Config.APPLICATION_ID)",
            Constants.POST_DEVICE_FIELD_VARIANT_ID: "\(Config.VARIANT_ID)",
            Constants.POST_DEVICE_FIELD_DEVICE_UUID: "\(record.data)",
            Constants.POST_DEVICE_FIELD_MANUFACTURER: "Apple",
            Constants.POST_DEVICE_FIELD_BRAND: "Apple",
            Constants.POST_DEVICE_FIELD_VERSION: "\(version)",
            Constants.POST_DEVICE_FIELD_MODEL: "\(model)",
            Constants.POST_DEVICE_FIELD_PLATFORM: "Iphone",
            Constants.POST_DEVICE_FIELD_SYNC_ID: "\(record.id)"
        ]
        print("Register Device parmameters: \(parameters)");
        
        let headers: HTTPHeaders = [
            .accept(Constants.HTTP_HEADER_ACCEPT)
        ]
        
        
        print("Register Device URL : \(Config.URL_DEVICE) ")
        
        AF.request(Config.URL_DEVICE, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers).responseJSON {response in
            
            print("Register Device Request")
            
            switch response.result {
                case .success:
                    let result = try? JSON(data: response.data!)
                    if result?["success"] ?? "" != false {
                        let aes = result?["data"]["aes"].stringValue ?? ""
                        let password = result?["data"]["password"].stringValue ?? ""
 
                        print("Register Device success = true aes : \(aes) password : \(password) ")
                        
                        if !aes.isEmpty && !password.isEmpty {

                            self.appData.deviceAes = aes
                            self.appData.devicePassword = password
                            self.appData.save()
                        }
                        
                        let sync_id = Int(result?["data"]["sync_id"].stringValue ?? "0") ?? 0
                        if sync_id > 0 {
                            self.syncDao.remove(id: sync_id)
                        }
                    } else {
                        print("Register Device success = false : \(result?["data"]))")
                    }
                break
                case .failure:
                    print("Register Device Failure : \(String(describing: Error.self))")
                break
            }
        }
    }
}