// // HomeViewController.swift // Vendoo // // Created by Okechi Onyeje on 5/26/16. // Copyright © 2016 Okechi Onyeje. All rights reserved. // import UIKit import Foundation /// This class is resonsible for retrieving all listing information for the current user. /// Acts as the tab bar controller for entire application. /// Responsible for retrieving notifications from each currently authorized network class HomeViewController: UITabBarController { //Web Service Managers let etsyManager: EtsyRESTAPIManager = EtsyRESTAPIManager() let fbGraphManager = FacebookGraphAPIManager() let firebaseManager = FirebaseManager() let ebayGraphManager = EbayWebServiceManager() //Retrieved Listing Variables for draft, current, ended, sold var userListings: [Listing] = [] var endedListings: [Listing] = [] var soldListings: [Listing] = [] var draftListings: [Listing] = [] //notification manager variables var notificationsManager = ServiceNotificationManager() var notifications: [Dictionary] = (NSUserDefaults.standardUserDefaults().objectForKey("notifications") == nil ? [] : (NSUserDefaults.standardUserDefaults().objectForKey("notifications") as! [Dictionary])) override func viewDidLoad() { super.viewDidLoad() NSUserDefaults.standardUserDefaults().removeObjectForKey("whichContent") //used to reset which webview is loaded in Faq and get started pages //initialize notifications manager ServiceNotificationManager.delegate = self self.notificationsManager.setManagers(fbGraphManager, fireManager: firebaseManager, ebayManager: ebayGraphManager, etsyManager: etsyManager) // Do any additional setup after loading the view. dispatch_group_notify(self.firebaseManager.firGroup, dispatch_get_main_queue(), { //get all listing information for current user self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").observeSingleEventOfType( .Value, withBlock: { (snapshot) -> Void in let userDict = snapshot.value as? [String : AnyObject] let listingDict = userDict!["user_Listings"] as? [String : AnyObject] //sync notifications (syncs only the notifications for networks that are currently authorized) if userDict!["notifications"] != nil { self.notifications = [] for (_, v) in userDict!["notifications"] as! [String : AnyObject] { if v["seen"] as! Bool == false{ var is_networkAuth = false switch((v["network"] as! String)){ case "ebay": is_networkAuth = NSUserDefaults.standardUserDefaults().boolForKey("ebayAuthorized") break case "etsy": is_networkAuth = NSUserDefaults.standardUserDefaults().boolForKey("etsyAuthorized") break case "facebook" : is_networkAuth = NSUserDefaults.standardUserDefaults().boolForKey("fbAuthorized") break case "amazon": break default: break } if is_networkAuth { self.notifications.append(v as! Dictionary) } } } NSUserDefaults.standardUserDefaults().setObject(self.notifications, forKey: "notifications") } NSUserDefaults.standardUserDefaults().setObject(userDict!["name"] as? String, forKey: "name") //check if user has any listings to track for notifications NSUserDefaults.standardUserDefaults().removeObjectForKey("isAnalytics") if listingDict != nil || !NSUserDefaults.standardUserDefaults().boolForKey("isAnalytics"){ var notificationStartTracker = 0 //number used to indicate when to start retrieving notifications dispatch_async(dispatch_get_main_queue(), { for (key, values) in listingDict! { //use this too make sure all listings are retrieved before showing listings in ItemsTableView let serviceGroup: dispatch_group_t = dispatch_group_create() self.firebaseManager.ref.observeSingleEventOfType(.Value, withBlock: { snapshot in let databaseDict = snapshot.value as! [String : AnyObject] let storageRef = self.firebaseManager.storage.referenceForURL((databaseDict["image_storage"] as? String)!) //Get Main image first let mainListingImage = storageRef.child("images/\(key)/main.jpg") dispatch_group_enter(serviceGroup) mainListingImage.dataWithMaxSize(10 * 1024 * 1024, completion: { (dataMain, error) -> Void in //for the case when there are connectivity issues, allows app to continue without waiting if(error != nil){ print("problem retrieving items") notificationStartTracker += 1 }else{ let mainImage = UIImage(data: dataMain!) var listingImages: [UIImage] = [mainImage!] //set of all images for this listing var count = 0 //indicates when checking of all supporting images are done //Get supporting images for i in 1...4 { let supportListingImg1 = storageRef.child("images/\(key)/\(i).jpg") supportListingImg1.dataWithMaxSize(10 * 1024 * 1024, completion: { (data1, error) -> Void in if(error != nil){ print("support image \(i) for key, \(key), does not exist") }else{ listingImages.append(UIImage(data: data1!)!) } print(key) count+=1 if(count == 4){ dispatch_group_leave(serviceGroup) notificationStartTracker += 1 } }) } //once images have been retrieved create a listing object with the reitrieved information dispatch_group_notify(serviceGroup, dispatch_get_main_queue(), { print(listingImages.count) let listingInfo = values as? [String : AnyObject] //if no Listing status found then the listing is either active or a draft if listingInfo!["listingStatus"] == nil { if(((listingInfo!["isListingDraft"] as! Bool))){ self.draftListings.append( Listing( itemTitle: (listingInfo!["listingTitle"] as? String)!, itemCategory: listingInfo!["listingCategory"] as? String, itemQuantity: (listingInfo!["listingQuantity"] as? String)!, itemPrice: listingInfo!["listingPrice"] as? String, itemDescription: listingInfo!["listingDescription"] as? String, itemImages: listingImages, isDraftListing: (listingInfo!["isListingDraft"] as? Bool)!, itemKey: key, networksSellingOn: (listingInfo!["networks"] as? Dictionary)! )) }else{ self.userListings.append( Listing( itemTitle: (listingInfo!["listingTitle"] as? String)!, itemCategory: listingInfo!["listingCategory"] as? String, itemQuantity: (listingInfo!["listingQuantity"] as? String)!, itemPrice: listingInfo!["listingPrice"] as? String, itemDescription: listingInfo!["listingDescription"] as? String, itemImages: listingImages, isDraftListing: (listingInfo!["isListingDraft"] as? Bool)!, itemKey: key, networksSellingOn: (listingInfo!["networks"] as? Dictionary)! )) } } //create ended Listing objects else if listingInfo!["listingStatus"] as? String == "Ended" { self.endedListings.append( Listing(itemTitle: (listingInfo!["listingTitle"] as? String)!, itemCategory: listingInfo!["listingCategory"] as? String, itemQuantity: (listingInfo!["listingQuantity"] as? String)!, itemPrice: listingInfo!["listingPrice"] as? String, itemDescription: listingInfo!["listingDescription"] as? String, itemImages: listingImages, isDraftListing: (listingInfo!["isListingDraft"] as? Bool)!, itemKey: key, networksSellingOn: (listingInfo!["networks"] as? Dictionary)! )) } //create sold Listing object else if listingInfo!["listingStatus"] as? String == "Sold" { self.soldListings.append( Listing(itemTitle: (listingInfo!["listingTitle"] as? String)!, itemCategory: listingInfo!["listingCategory"] as? String, itemQuantity: (listingInfo!["listingQuantity"] as? String)!, itemPrice: listingInfo!["listingPrice"] as? String, itemDescription: listingInfo!["listingDescription"] as? String, itemImages: listingImages, isDraftListing: (listingInfo!["isListingDraft"] as? Bool)!, itemKey: key, networksSellingOn: (listingInfo!["networks"] as? Dictionary)! )) } print(notificationStartTracker) //once all listings have been retrieved and processed start retrieving possible notifications if(notificationStartTracker == listingDict?.count){ self.userListings.sortInPlace({$0.title.lowercaseString < $1.title.lowercaseString}) self.draftListings.sortInPlace({$0.title.lowercaseString < $1.title.lowercaseString}) self.endedListings.sortInPlace({$0.title.lowercaseString < $1.title.lowercaseString}) self.soldListings.sortInPlace({$0.title.lowercaseString < $1.title.lowercaseString}) NSNotificationCenter.defaultCenter().postNotificationName("finished_fetching_listings", object: nil) self.notificationsManager.setListings(self.userListings) self.notificationsManager.startServicePolling() } }) } }) }) } }) }else { NSNotificationCenter.defaultCenter().postNotificationName("finished_fetching_listings", object: nil) } }) }) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Navigation // In a storyboard-based application, you will often want to do a little preparation before navigation override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // Get the new view controller using segue.destinationViewController. // Pass the selected object to the new view controller. } } extension HomeViewController: ServiceNotificationManagerDelegate { func listingHasFinishedRetrievingNotifications() { NSUserDefaults.standardUserDefaults().setObject(self.notifications, forKey: "notifications") } func listingHasStartedRetrievingNotifications() { //can be iterated upon to do work when notification retrieval process starts } //delegate method that is used to add notifications to global notifications set func listingHasEnded(fbInfo: AnyObject?, ebayInfo: AnyObject?, amazonInfo: AnyObject?, etsyInfo: AnyObject?) { var notificationArray: [[String: AnyObject]] = self.notifications if (fbInfo != nil) { notificationArray.append( [ "network": "facebook", "message": (ebayInfo as! [String : AnyObject])["notification"] as! String, "type": "ended", "seen":false, "key": (ebayInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] ) } if (ebayInfo != nil) { let notification = [ "network": "ebay", "message": (ebayInfo as! [String : AnyObject])["notification"] as! String, "type": (ebayInfo as! [String : AnyObject])["type"] as! String, "seen":false, "key": (ebayInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] notificationArray.append( notification as! [String : AnyObject] ) //Move listing from active to ended on local system self.endedListings.appendContentsOf( self.userListings.filter({$0.key == ((ebayInfo as! [String : AnyObject])["listingKey"] as! String)})) self.userListings = self.userListings.filter({$0.key != ((ebayInfo as! [String : AnyObject])["listingKey"] as! String)}) let itemsView = self.viewControllers![0] as! ItemTableViewController //Move listing from active to ended and save new notifications to Firebase self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").observeSingleEventOfType( .Value, withBlock: { (snapshot) -> Void in var userDict = snapshot.value as? [String : AnyObject] var notifications = userDict!["notifications"] as? [String: AnyObject] //get the current notifications from firebase if notifications == nil { userDict!["notifications"] = [((ebayInfo as! [String : AnyObject])["listingKey"] as! String):notification] }else { notifications![((ebayInfo as! [String : AnyObject])["listingKey"] as! String)] = notification userDict!["notifications"] = notifications } var listings = userDict!["user_Listings"] as! [String: AnyObject] var listingDict = (listings[((ebayInfo as! [String : AnyObject])["listingKey"] as! String)] as! [String : AnyObject]) listingDict["listingStatus"] = "Ended" //save everything back to their respective dictionaries listings[((ebayInfo as! [String : AnyObject])["listingKey"] as! String)] = listingDict userDict!["user_Listings"] = listings self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").setValue(userDict, withCompletionBlock: { (error, reference) -> Void in if error == nil { //reload data for notifications NSUserDefaults.standardUserDefaults().setObject(notificationArray, forKey: "notifications") itemsView.itemTable.reloadData() } }) }) } if (amazonInfo != nil) { notificationArray.append( [ "network": "amazon", "message": (ebayInfo as! [String : AnyObject])["notification"] as! String, "type": (ebayInfo as! [String : AnyObject])["type"] as! String, "seen":false, "key": (ebayInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] ) } if (etsyInfo != nil) { let notification = [ "network": "etsy", "message": (etsyInfo as! [String : AnyObject])["notification"] as! String, "type": "ended", "seen":false, "key": (etsyInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] notificationArray.append( notification as! [String : AnyObject] ) //Move listing from active to ended on local system self.endedListings.appendContentsOf( self.userListings.filter({$0.key == ((etsyInfo as! [String : AnyObject])["listingKey"] as! String)})) self.userListings = self.userListings.filter({$0.key != ((etsyInfo as! [String : AnyObject])["listingKey"] as! String)}) let itemsView = self.viewControllers![0] as! ItemTableViewController //Move listing from active to ended and save new notifications to Firebase self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").observeSingleEventOfType( .Value, withBlock: { (snapshot) -> Void in var userDict = snapshot.value as? [String : AnyObject] var notifications = userDict!["notifications"] as? [String: AnyObject] if notifications == nil { userDict!["notifications"] = [((etsyInfo as! [String : AnyObject])["listingKey"] as! String):notification] }else { notifications![((etsyInfo as! [String : AnyObject])["listingKey"] as! String)] = notification //get the current notifications from firebase userDict!["notifications"] = notifications } var listings = userDict!["user_Listings"] as! [String: AnyObject] var listingDict = (listings[((etsyInfo as! [String : AnyObject])["listingKey"] as! String)] as! [String : AnyObject]) listingDict["listingStatus"] = "Ended" //save everything back to their respective dictionaries listings[((etsyInfo as! [String : AnyObject])["listingKey"] as! String)] = listingDict userDict!["user_Listings"] = listings self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").setValue(userDict, withCompletionBlock: { (error, reference) -> Void in if error == nil { //reload data for notifications NSUserDefaults.standardUserDefaults().setObject(notificationArray, forKey: "notifications") itemsView.itemTable.reloadData() } }) }) } } //delegate function called mostly by facebook notification when a new comment is posted func listingHasNewNotifications(fbInfo: AnyObject?, ebayInfo: AnyObject?, amazonInfo: AnyObject?, etsyInfo: AnyObject?) { var notificationArray: [Dictionary] = self.notifications if (fbInfo != nil) { notificationArray.append(fbInfo as! [String : AnyObject]) self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").observeSingleEventOfType(.Value, withBlock: { (snapshot) -> Void in var userDict = snapshot.value as? [String : AnyObject] //check if there are any notifications currently, if not then create a notifications directory in firebase and append notification to it if (userDict!["notifications"] != nil) { var notificationsFir = userDict!["notifications"] as! [String : AnyObject] notificationsFir[fbInfo!["UUID"] as! String] = fbInfo self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)/notifications").setValue(notificationsFir, withCompletionBlock: { (error, reference) -> Void in if error == nil { NSUserDefaults.standardUserDefaults().setObject(notificationArray, forKey: "notifications") } }) }else { //if notification directory already exists append existing notification to it let id = (fbInfo!["UUID"] as! String) print(id) userDict!["notifications"] = ([ id : fbInfo as! [String:AnyObject]]) self.firebaseManager.ref.child("Users/\(self.firebaseManager.user_email)").setValue(userDict, withCompletionBlock: { (error, reference) -> Void in if error == nil { NSUserDefaults.standardUserDefaults().setObject(notificationArray, forKey: "notifications") } }) } }) } if (ebayInfo != nil) { notificationArray.append( [ "network": "ebay", "message": (ebayInfo as! [String : AnyObject])["notification"] as! String, "type": (ebayInfo as! [String : AnyObject])["type"] as! String, "key": (ebayInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] ) } if (amazonInfo != nil) { notificationArray.append( [ "network": "amazon", "message": (ebayInfo as! [String : AnyObject])["notification"] as! String, "type": "", "key": (ebayInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] ) } if (etsyInfo != nil) { notificationArray.append( [ "network": "etsy", "message": (etsyInfo as! [String : AnyObject])["notification"] as! String, "type": (etsyInfo as! [String : AnyObject])["type"] as! String, "key": (etsyInfo as! [String : AnyObject])["listingKey"] as! String, "UUID": NSUUID().UUIDString ] ) } } }