//
//  LoadingAnimationViewModel.swift
//  Learn Genie
//
//  Created by Suraj Kumar Mandal on 25/09/21.
//

import Foundation
import Alamofire
import SSZipArchive
import RealmSwift

class LoadingAnimationViewModel {
    
    var delegate : LoadingAnimationViewProtocol?
    
    func generateCookie() {
        //DBManager.sharedInstance.deleteAllDatabase()
        if let delegate = delegate {
            let url = ApiUrl.BASE_URL + ApiUrl.API_AUTH
            let params: [String:Any]?
            params = [
                "username" : "admin",
                "password" : "mahindrapass123"
            ]
            print(params!)
            
            AF.request(url, method: HTTPMethod.post, parameters: params).responseData { (responseObject) -> Void in
                
                if let responseStatus = responseObject.response?.statusCode {
                    if responseStatus != 200 {
                        // error
                        print("error...")
                    } else {
                        // view all cookies
                        print(HTTPCookieStorage.shared.cookies!)
                        for cookie in HTTPCookieStorage.shared.cookies! {
                            print(cookie.value)
                            UserDefaultsConstant.setValueInUserDefaults(objValue: cookie.value, for: "cookieValue")
                            //self.topicDownloader()
                            delegate.callDataAPI()
                        }
                    }
                }
            }
        }
    }
    
    func topicDownloader() {
        if let delegate = delegate {
            let language = DBManager.sharedInstance.database.objects(LanguageModel.self)
            for item in language {
                let topicData = DBManager.sharedInstance.database.objects(TopicModel.self)
                for data in topicData {
                    let id = data.id
                    //let selectedLanguage = UserDefaultsConstant.getValueFromUserDefults(for: "selectedLanguage") ?? ""
                    let url = "\(ApiUrl.BASE_URL + ApiUrl.API_DOWNLOAD_TOPIC)?topic=\(id)&lang=\(item.shortName)"
                    let saveName = "\(id).zip"
                    print(url)
                    
                    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                    let dataPath = documentsDirectory.appendingPathComponent(item.name)
                    
                    do {
                        try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
                    } catch let error as NSError {
                        print("Error creating directory: \(error.localizedDescription)")
                    }
                    
                    // file location to save download file
                    let destination: DownloadRequest.Destination = { _, _ in
                        var documentsURL = dataPath
                        documentsURL.appendPathComponent(saveName)
                        return (documentsURL, [.removePreviousFile])
                    }
                    
                    let unZipDestination = dataPath
                    let unZipUrl = unZipDestination.appendingPathComponent("\(id)")
                    print(unZipUrl)
                    
                    // Alamofire to download file
                    AF.download(url, to: destination).responseData { response in
                        switch response.result {
                        case .success:
                            // write something here
                            if response.fileURL != nil {
                                print(response.fileURL!)
                                let filePath = response.fileURL
                                SSZipArchive.unzipFile(atPath: filePath!.path, toDestination: unZipUrl.path)
                            }
                        case .failure:
                            print(response.result)
                        }
                    }
                }
            }
            delegate.groupLeave()
        }
        //self.getLevel()
    }
    
    func getLevel() {
        if let delegate = delegate {
            let url = "\(ApiUrl.BASE_URL + ApiUrl.API_LEVEL).json"
            let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
            let headers: HTTPHeaders = [
                "Content-Type": "application/json",
                "Accept": "application/json",
                "Cookie": "\(Constant.CookieName) = \(cookieValue)"
            ]
            print(headers)
            print(url)
            
            AF.request(url, method: .get, encoding: URLEncoding.httpBody, headers: headers).responseJSON { response in
                
                switch response.result {
                case .success(let value):
                    
                    let levelArray = value as! [NSDictionary]
                    print(levelArray)
                    
                    for item in levelArray {
                        let id = item.value(forKey: "id") as! NSNumber;
                        let dateCreated = item.value(forKey: "dateCreated") as? String ?? "";
                        let lastUpdated = item.value(forKey: "lastUpdated") as? String ?? "";
                        let name = item.value(forKey: "name") as? String ?? "" ;
                        let topics = item.value(forKey: "topics") as! [NSDictionary];
                        let topicIdModel = List<Topics>()
                        for data in topics {
                            let topicId = data.value(forKey: "id") as? NSNumber;
                            let newTopics = Topics(id: topicId as! Int)
                            topicIdModel.append(newTopics)
                        }
                        let iconBytes = item.value(forKey: "iconBytes") as! NSArray;
                        let iconByteString = iconBytes.map { String(describing: $0) }.joined(separator: ",")
                        
                        var levelModel = [LevelModel]()
                        
                        let newlevelModel = LevelModel(id: Int(truncating: id), dateCreated: dateCreated, lastUpdated: lastUpdated, name: name, topics: topicIdModel, iconByte: iconByteString)
                        print("Level Model: \(newlevelModel)")
                        levelModel.append(newlevelModel)
                        
                        DBManager.sharedInstance.addData(objs: levelModel)
                    }
                    let realmEntries = DBManager.sharedInstance.database.objects(LevelModel.self)
                    
                    print("level count")
                    print(realmEntries.count)
                    //Next API call
                    //self.getQuestionBank(offset: 0)
                    delegate.groupLeave()
                    
                case .failure(let error):
                    print(error)
                }
            }
        }
    }
    
    func getQuestionBank(offset:Int) {
        if let delegate = delegate {
            let max = 10
            let url = "\(ApiUrl.BASE_URL + ApiUrl.API_QUESTION_BANK).json?max=\(max)&offset=\(offset)"
            let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
            let headers: HTTPHeaders = [
                "Content-Type": "application/json",
                "Accept": "application/json",
                "Cookie": "\(Constant.CookieName) = \(cookieValue)"
            ]
            print(headers)
            print(url)
            
            AF.request(url, method: .get, encoding: URLEncoding.httpBody, headers: headers).responseJSON { response in
                
                switch response.result {
                case .success(let value):
                    
                    let quesBankArray = value as! [NSDictionary]
                    
                    if quesBankArray != [] {
                        print(quesBankArray)
                        
                        for item in quesBankArray {
                            let id = item.value(forKey: "id") as! NSNumber;
                            let dateCreated = item.value(forKey: "dateCreated") as? String ?? "";
                            let lastUpdated = item.value(forKey: "lastUpdated") as? String ?? "";
                            let name = item.value(forKey: "name") as? String ?? "" ;
                            let questions = item.value(forKey: "questions") as! [NSDictionary];
                            let questionIdModel = List<Questions>()
                            for data in questions {
                                let quesId = data.value(forKey: "id") as? NSNumber;
                                let newQues = Questions(id: quesId as! Int)
                                questionIdModel.append(newQues)
                            }
                            
                            var quesBankModel = [QuestionBankModel]()
                            
                            let newQuesBankModel = QuestionBankModel(id: Int(truncating: id), dateCreated: dateCreated, lastUpdated: lastUpdated, name: name, questions: questionIdModel)
                            print("Question Bank Model: \(newQuesBankModel)")
                            quesBankModel.append(newQuesBankModel)
                            
                            DBManager.sharedInstance.addData(objs: quesBankModel)
                        }
                        let realmEntries = DBManager.sharedInstance.database.objects(QuestionBankModel.self)
                        
                        print("question bank count")
                        print(realmEntries.count)
                        self.getQuestionBank(offset: offset + max)
                    } else {
                        //Next API call
                        //self.getQuestion(offset: 0)
                        delegate.groupLeave()
                    }
                    
                case .failure(let error):
                    print(error)
                }
            }
        }
    }
    
    func getQuestion(offset:Int) {
        if let delegate = delegate {
            let max = 10
            let url = "\(ApiUrl.BASE_URL + ApiUrl.API_QUESTION).json?max=\(max)&offset=\(offset)"
            let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
            let headers: HTTPHeaders = [
                "Content-Type": "application/json",
                "Accept": "application/json",
                "Cookie": "\(Constant.CookieName) = \(cookieValue)"
            ]
            print(headers)
            print(url)
            
            AF.request(url, method: .get, encoding: URLEncoding.httpBody, headers: headers).responseJSON { response in
                
                switch response.result {
                case .success(let value):
                    
                    let questionArray = value as! [NSDictionary]
                    
                    if questionArray != [] {
                        print(questionArray)
                        
                        for item in questionArray {
                            let id = item.value(forKey: "id") as! NSNumber;
                            let dateCreated = item.value(forKey: "dateCreated") as? String ?? "";
                            let lastUpdated = item.value(forKey: "lastUpdated") as? String ?? "";
                            let content = item.value(forKey: "content") as? String ?? "" ;
                            let questionBank = item.value(forKey: "questionBank") as? NSObject;
                            let questionBankId = questionBank?.value(forKey: "id") as! NSNumber;
                            let answer = item.value(forKey: "answer") as? NSObject;
                            let answerId = answer?.value(forKey: "id") as! NSNumber;
                            let choices = item.value(forKey: "choices") as! [NSDictionary];
                            let choicesIdModel = List<Choices>()
                            for data in choices {
                                let choicesId = data.value(forKey: "id") as? NSNumber;
                                let newchoices = Choices(id: choicesId as! Int)
                                choicesIdModel.append(newchoices)
                            }
                            
                            var quesModel = [QuestionModel]()
                            
                            let newQuesModel = QuestionModel(id: Int(truncating: id), dateCreated: dateCreated, lastUpdated: lastUpdated, content: content, questionBankId: Int(truncating: questionBankId), answerId: Int(truncating: answerId), choices: choicesIdModel)
                            print("Question Model: \(newQuesModel)")
                            quesModel.append(newQuesModel)
                            
                            DBManager.sharedInstance.addData(objs: quesModel)
                        }
                        let realmEntries = DBManager.sharedInstance.database.objects(QuestionModel.self)
                        
                        print("question count")
                        print(realmEntries.count)
                        self.getQuestion(offset: offset + max)
                    } else {
                        //Next API call
                        //self.getChoice(offset: 0)
                        delegate.groupLeave()
                    }
                    
                case .failure(let error):
                    print(error)
                }
            }
        }
    }
    
    func getChoice(offset:Int) {
        if let delegate = delegate {
            let max = 10
            let url = "\(ApiUrl.BASE_URL + ApiUrl.API_CHOICE).json?max=\(max)&offset=\(offset)"
            let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
            let headers: HTTPHeaders = [
                "Content-Type": "application/json",
                "Accept": "application/json",
                "Cookie": "\(Constant.CookieName) = \(cookieValue)"
            ]
            print(headers)
            print(url)
            
            AF.request(url, method: .get, encoding: URLEncoding.httpBody, headers: headers).responseJSON { response in
                
                switch response.result {
                case .success(let value):
                    
                    let choiceArray = value as! [NSDictionary]
                    
                    if choiceArray != [] {
                        print(choiceArray)
                        
                        for item in choiceArray {
                            
                            let id = item.value(forKey: "id") as! NSNumber;
                            let content = item.value(forKey: "content") as? String ?? "";
                            let question = item.value(forKey: "question") as? NSObject;
                            let questionId = question?.value(forKey: "id") as! NSNumber;
                            
                            var choiceModel = [ChoiceModel]()
                            
                            let newchoiceModel = ChoiceModel(id: Int(truncating: id), content: content, questionId: Int(truncating: questionId))
                            print("Choice Model: \(newchoiceModel)")
                            choiceModel.append(newchoiceModel)
                            
                            DBManager.sharedInstance.addData(objs: choiceModel)
                        }
                        let realmEntries = DBManager.sharedInstance.database.objects(ChoiceModel.self)
                        
                        print("choice count")
                        print(realmEntries.count)
                        self.getChoice(offset: offset + max)
                    } else {
                        delegate.groupLeave()
                    }
                    
                case .failure(let error):
                    print(error)
                }
            }
        }
    }
    
    func getScoreBoard() {
        if let delegate = delegate {
            if UserDefaultsConstant.getValueFromUserDefults(for: Constant.signInMethod) as! String == "google" {
                let studentId = UserDefaultsConstant.getIntValueFromUserDefults(for: Constant.studentId) as! Int
                let url = ApiUrl.BASE_URL + ApiUrl.API_SEARCH_SCOREBOARD
                let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
                let headers: HTTPHeaders = [
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                    "Cookie": "\(Constant.CookieName) = \(cookieValue)"
                ]
                print(headers)

                let params: Parameters?
                params = [
                    "id" : studentId
                ]
                print(params!)

                AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { response in

                    switch response.result {
                    case .success(let value):

                        let scoreData = value as! [NSDictionary]
                        print(scoreData)
                        var currentIndex = 0

                        for item in scoreData {
                            let student = item.value(forKey: "student") as! NSObject;
                            let studentId = student.value(forKey: "id") as! NSNumber;
                            let topic = item.value(forKey: "topic") as! NSObject;
                            let topicId = topic.value(forKey: "id") as! NSNumber;
                            let level = item.value(forKey: "level") as! NSObject;
                            let levelId = level.value(forKey: "id") as! NSNumber;
                            let runs = item.value(forKey: "runs") as! NSNumber;
                            let wickets = item.value(forKey: "wickets") as! NSNumber;
                            let noOfAttempts = item.value(forKey: "noOfAttempts") as! NSNumber;

                            var saveScoreModel = [SaveScoreBoard]()
                            currentIndex += 1
                            let newSaveScoreModel = SaveScoreBoard(id: currentIndex, levelId: Int(truncating: levelId), topicId: Int(truncating: topicId), runs: Int(truncating: runs), wickets: Int(truncating: wickets), noOfAttempts: Int(truncating: noOfAttempts), student: Int(truncating: studentId), synced: true)

                            saveScoreModel.append(newSaveScoreModel)

                            DBManager.sharedInstance.addData(objs: saveScoreModel)
                        }
                        let saveScoreDB = DBManager.sharedInstance.database.objects(SaveScoreBoard.self)

                        print("save score count")
                        print(saveScoreDB.count)
                        //Next API call
                        //delegate.stopActivityIndicator()
                        //delegate.navigation()
                        delegate.groupLeave()

                    case .failure(let error):
                        print(error)
                    }
                }
            } else {
                let userModel = DBManager.sharedInstance.database.objects(UserDetailsModel.self)
                let userIdentifier = UserDefaultsConstant.getValueFromUserDefults(for: Constant.userIdentifier) as! String
                if userModel.contains(where: {$0.appleIdentifier == userIdentifier}) {
                    let studentId = UserDefaultsConstant.getIntValueFromUserDefults(for: Constant.studentId) as! Int
                    let url = ApiUrl.BASE_URL + ApiUrl.API_SEARCH_SCOREBOARD
                    let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
                    let headers: HTTPHeaders = [
                        "Content-Type": "application/json",
                        "Accept": "application/json",
                        "Cookie": "\(Constant.CookieName) = \(cookieValue)"
                    ]
                    print(headers)

                    let params: Parameters?
                    params = [
                        "id" : studentId
                    ]
                    print(params!)

                    AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { response in

                        switch response.result {
                        case .success(let value):

                            let scoreData = value as! [NSDictionary]
                            var currentIndex = 0

                            for item in scoreData {
                                let student = item.value(forKey: "student") as! NSObject;
                                let studentId = student.value(forKey: "id") as! NSNumber;
                                let topic = item.value(forKey: "topic") as! NSObject;
                                let topicId = topic.value(forKey: "id") as! NSNumber;
                                let level = item.value(forKey: "level") as! NSObject;
                                let levelId = level.value(forKey: "id") as! NSNumber;
                                let runs = item.value(forKey: "runs") as! NSNumber;
                                let wickets = item.value(forKey: "wickets") as! NSNumber;
                                let noOfAttempts = item.value(forKey: "noOfAttempts") as! NSNumber;

                                var saveScoreModel = [SaveScoreBoard]()
                                currentIndex += 1
                                let newSaveScoreModel = SaveScoreBoard(id: currentIndex, levelId: Int(truncating: levelId), topicId: Int(truncating: topicId), runs: Int(truncating: runs), wickets: Int(truncating: wickets), noOfAttempts: Int(truncating: noOfAttempts), student: Int(truncating: studentId), synced: true)

                                saveScoreModel.append(newSaveScoreModel)

                                DBManager.sharedInstance.addData(objs: saveScoreModel)
                            }
                            let saveScoreDB = DBManager.sharedInstance.database.objects(SaveScoreBoard.self)

                            print("save score count")
                            print(saveScoreDB.count)
                            //Next API call
                            //delegate.stopActivityIndicator()
                            //delegate.navigation()
                            delegate.groupLeave()

                        case .failure(let error):
                            print(error)
                        }
                    }
                } else {
                    delegate.groupLeave()
                }
            }
        }
    }
    
}

protocol LoadingAnimationViewProtocol {
    func callDataAPI()
    func groupLeave()
    func stopActivityIndicator()
    func showToastMessage(message:String)
    func navigation()
}