// // ListingPreviewViewController.swift // Vendoo // // Created by Okechi Onyeje on 5/28/16. // Copyright © 2016 Okechi Onyeje. All rights reserved. // /* NOTES: need to display navigation bar so user can navigate back to previous screens if changes need to be made */ import UIKit import FirebaseStorage import SWRevealViewController //@TODO: Need to make multiple images work for etsy and facebook and need to implement multiple images saving to firebase class ListingPreviewViewController: UIViewController { //IBOutlets @IBOutlet weak var containerScrollView: UIScrollView! @IBOutlet weak var itemQuantity: UITextView! @IBOutlet weak var itemPictureMain: UIImageView! @IBOutlet weak var itemPictureSup1: UIImageView! @IBOutlet weak var itemPictureSup2: UIImageView! @IBOutlet weak var itemPictureSup3: UIImageView! @IBOutlet weak var itemPictureSup4: UIImageView! @IBOutlet weak var itemTitle: UITextView! @IBOutlet weak var itemDescription: UITextView! @IBOutlet weak var itemPrice: UITextView! @IBOutlet weak var itemCategory: UITextView! @IBOutlet weak var networks: UICollectionView! @IBOutlet weak var publishBtn: UIButton! @IBOutlet weak var edit_button: UIButton! @IBOutlet weak var cancel_backBtn: UIButton! //class variables private var networksDictionary: Dictionary = Dictionary() private var graphManager: FacebookGraphAPIManager! = nil private var firManager: FirebaseManager! = nil private var ebayManager: EbayWebServiceManager! = nil private var etsyManager: EtsyRESTAPIManager! = nil private var itemListingDictionary: Dictionary! = Dictionary() private var alert = UIAlertController(title: "Listing Published", message: "Your listing has been published", preferredStyle: .Alert) private var lastListingKey: String! private var newInProgressListing: Dictionary = Dictionary() var loadingView: UIView! private var itemViewState = "" private var selectedNetworks : [String] = [] override func viewDidLoad() { super.viewDidLoad() if (self.itemViewState == "NonEditable") { dispatch_async(dispatch_get_main_queue(), { //self.cancel_backBtn.titleLabel?.text = "Back" self.edit_button.hidden = true self.edit_button.enabled = false self.publishBtn.hidden = true self.publishBtn.enabled = false }) } /*if(!self.networksDictionary["areNetworksChosen"]!) { self.networks.hidden = true }*/ else if (self.itemViewState == "Editible") { //self.cancel_backBtn.titleLabel?.text = "Back" if( self.itemTitle.text == "" || self.itemDescription.text == "" || self.itemPrice.text == "" || self.itemCategory.text == "" || self.itemQuantity == nil || self.itemPictureMain.image == nil || self.networks.numberOfItemsInSection(0) == 0 ){ self.publishBtn.hidden = true self.publishBtn.enabled = false } } // Do any additional setup after loading the view. // Initialization code self.networks.delegate = self self.networks.dataSource = self self.networks.backgroundView?.backgroundColor = UIColor.whiteColor() //self.graphManager.delegate = self } override func viewDidAppear(animated: Bool) { self.setListing() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func setListing(){ for i in 0...((self.itemListingDictionary["pictures"] as! [UIImageView]).count - 1) { switch i { case 0: self.itemPictureMain.image = (self.itemListingDictionary["pictures"] as? [UIImageView])![i].image break case 1: self.itemPictureSup1.image = (self.itemListingDictionary["pictures"] as? [UIImageView])![i].image break case 2: self.itemPictureSup2.image = (self.itemListingDictionary["pictures"] as? [UIImageView])![i].image break case 3: self.itemPictureSup3.image = (self.itemListingDictionary["pictures"] as? [UIImageView])![i].image break case 4: self.itemPictureSup4.image = (self.itemListingDictionary["pictures"] as? [UIImageView])![i].image break default: break } } self.itemTitle.text = self.itemListingDictionary["title"] as! String self.itemDescription.text = self.itemListingDictionary["description"] as! String self.itemPrice.text = self.itemListingDictionary["price"] as! String self.itemCategory.text = self.itemListingDictionary["category"] as! String self.itemQuantity.text = self.itemListingDictionary["quantity"] as! String } func setViewState(state: String) { self.itemViewState = state } func setDictionary(netdictionary:Dictionary, itemdictionary: Dictionary){ self.networksDictionary = netdictionary for (k,v) in self.networksDictionary { if ((k != "areNetworksChosen") && v) { self.selectedNetworks.append("\(k)_icon") } } self.itemListingDictionary = itemdictionary } func setManagers(fbManager: FacebookGraphAPIManager, fireManager: FirebaseManager, ebayManager: EbayWebServiceManager, etsyManager: EtsyRESTAPIManager){ self.graphManager = fbManager self.firManager = fireManager self.ebayManager = ebayManager self.etsyManager = etsyManager } func saveToFirebase(listingImageRef: FIRStorageReference, completion: ServiceResponse! , index: Int!) { var image: UIImage! switch(index){ case 0: image = self.itemPictureMain.image! break case 1: image = self.itemPictureSup1.image! break case 2: image = self.itemPictureSup2.image! break case 3: image = self.itemPictureSup3.image! break case 4: image = self.itemPictureSup4.image! break default: break } listingImageRef.putData(UIImageJPEGRepresentation(image, 0.8)!, metadata: nil,completion: { (metadata, error) -> Void in completion(metadata, error) }) } // 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. if(segue.identifier == "EditListingSegue"){ var imageData: [UIImage] = [] for imageView in (self.itemListingDictionary["pictures"] as? [UIImageView])! { imageData.append(imageView.image!) } let dict: Dictionary = ["title": self.itemTitle.text, "description": self.itemDescription.text, "price": self.itemPrice.text, "quantity": self.itemQuantity.text, "images": imageData, "category": self.itemCategory.text, "fbManager": self.graphManager, "ebayManager": self.ebayManager, "etsyManager": self.etsyManager, "firebaseManager": self.firManager] let vc = (segue.destinationViewController as? ItemImagePickerViewController)! vc.toggleEditingMode(dict) } } } extension Dictionary { mutating func update(other:Dictionary) { for (key,value) in other { self.updateValue(value, forKey:key) } } } //MARK: - IBActions extension ListingPreviewViewController { @IBAction func cancel(sender: AnyObject) { if self.itemViewState == "" { let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) let vc = storyboard.instantiateViewControllerWithIdentifier("Reveal View Controller") as! SWRevealViewController self.presentViewController(vc, animated: true, completion: nil) } else if self.itemViewState == "Editible" || self.itemViewState == "NonEditable"{ self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil) } } @IBAction func publishItem(sender: AnyObject) { self.loadingView = UIView(frame: self.view.frame) self.loadingView.backgroundColor = UIColor.grayColor() self.loadingView.alpha = 0.4 self.firManager.indicator.center = self.view.center self.loadingView.addSubview(self.firManager.indicator) self.view.addSubview(loadingView) self.firManager.indicator.startAnimating() if(self.itemPictureMain.image == nil){ let alert = UIAlertController(title: "Image Needed", message: "To proceed to choose networks, you must supply at least one picture for your listing", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in alert.dismissViewControllerAnimated(true, completion: nil)})) self.presentViewController(alert, animated: true, completion: nil) }else{ self.networksDictionary["areNetworksChosen"] = true //save listing to private user path in firebase let newListingRef = self.firManager.ref.child("Users").child("\(self.firManager.user_email)").child("user_Listings").childByAutoId() let postingGroup: dispatch_group_t = dispatch_group_create() //post to amazon if(self.networksDictionary["amazon"]!){ } //post to etsy if(self.networksDictionary["etsy"]!){ dispatch_group_enter(postingGroup) var categoryCode: Int! switch self.itemCategory.text { case "Accessories": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["accessories"] as! Int break case "Art": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["art"] as! Int break case "Bath, Beauty & Health": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["bath_and_beauty"] as! Int break case "Bags & Purses": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["bags_and_purses"] as! Int break case "Books": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["books_and_zines"] as! Int break case "Candles": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["candles"] as! Int break case "Ceramics & Pottery": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["ceramics_and_pottery"] as! Int break case "Children": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["children"] as! Int break case "Clothing & Shoes": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["clothing"] as! Int break case "Crochet": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["crochet"] as! Int break case "Dolls and Bears": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["dolls_and_miniatures"] as! Int break case "Everything Else": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["everything_else"] as! Int break case "Furniture": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["furniture"] as! Int break case "Geekery": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["geekery"] as! Int break case "Glass": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["glass"] as! Int break case "Holidays": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["holidays"] as! Int break case "Home/Houseware & Garden": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["housewares"] as! Int break case "Jewelry & Watches": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["jewelry"] as! Int break case "Knitting": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["knitting"] as! Int break case "Music": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["music"] as! Int break case "Needlecraft": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["needlecraft"] as! Int break case "Paper Goods": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["paper_goods"] as! Int break case "Patterns": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["patterns"] as! Int break case "Plants and Edibles": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["plants_and_edibles"] as! Int break case "Quilts": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["quilts"] as! Int break case "Supplies": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["supplies"] as! Int break case "Toys & Hobbies": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["toys"] as! Int break case "Vintage": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["vintage"] as! Int break case "Wedding": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["weddings"] as! Int break case "Woodworking": categoryCode = EtsyRESTAPIManager.settingsDictionary["categories"]!["woodworking"] as! Int break default: break } let body: [String: AnyObject] = [ "title": self.itemTitle.text, "quantity":self.itemQuantity.text, "description":self.itemDescription.text, "price":self.itemPrice.text, "category_id":categoryCode, "who_made": EtsyRESTAPIManager.settingsDictionary["who_made"] as! String, "is_supply": EtsyRESTAPIManager.settingsDictionary["is_supply"]!, "when_made": EtsyRESTAPIManager.settingsDictionary["when_made"] as! String, "shipping_template_id": EtsyRESTAPIManager.settingsDictionary["shipping_template_id"] as! Int, "state":"active" ] self.etsyManager.sendPOSTRequest("/private/listings", body: body, onCompletion: { (dict, error) -> Void in var results = (dict as! [[String : AnyObject]])[0] if((self.newInProgressListing["networkIDs"] == nil)){ self.newInProgressListing["networkIDs"] = Dictionary() } var networkIDs = (self.newInProgressListing["networkIDs"] as! Dictionary) networkIDs["etsy"] = results["listing_id"] as? Int self.newInProgressListing["networkIDs"] = networkIDs /*let tmpDirURL = NSURL.fileURLWithPath(NSTemporaryDirectory(), isDirectory: true) let fileURL = tmpDirURL.URLByAppendingPathComponent("main").URLByAppendingPathExtension("jpg") print("FilePath: \(fileURL.path!)") do { try UIImageJPEGRepresentation(self.itemPictureMain.image!, 0.45)!.writeToFile(fileURL.path!, options: NSDataWritingOptions.AtomicWrite) }catch{ (error) print(error) }*/ var imageBody: [String: AnyObject] = ["listing_id": networkIDs["etsy"] as! Int, "type":"image/jpg"] for i in 0...(self.itemListingDictionary["pictures"] as! [UIImageView]).count - 1 { switch (i) { case 0: imageBody["imageMain"] = UIImageJPEGRepresentation(self.itemPictureMain.image!, 0.45)! imageBody["imgCount"] = 1 break case 1: imageBody["image1"] = UIImageJPEGRepresentation(self.itemPictureSup1.image!, 0.45)! imageBody["imgCount"] = 2 break case 2: imageBody["image2"] = UIImageJPEGRepresentation(self.itemPictureSup2.image!, 0.45)! imageBody["imgCount"] = 3 break case 3: imageBody["image3"] = UIImageJPEGRepresentation(self.itemPictureMain.image!, 0.45)! imageBody["imgCount"] = 4 break case 4: imageBody["image4"] = UIImageJPEGRepresentation(self.itemPictureSup4.image!, 0.45)! imageBody["imgCount"] = 5 break default: break } } dispatch_group_leave(postingGroup) //@FIXME: Need to make etsy work with pictures /*self.etsyManager.sendPOSTRequest(("/private/listings/\(networkIDs["etsy"] as! Int)/images"), body: imageBody, onCompletion: { (dict, error) -> Void in dispatch_group_leave(postingGroup) })*/ }) } //post to facebook if(self.networksDictionary["facebook"]!){ dispatch_group_enter(postingGroup) let fb_group: dispatch_group_t = dispatch_group_create() let tmpDirURL = NSURL.fileURLWithPath(NSTemporaryDirectory(), isDirectory: true) let fileURL = tmpDirURL.URLByAppendingPathComponent("main").URLByAppendingPathExtension("jpg") print("FilePath: \(fileURL.path!)") do { try UIImageJPEGRepresentation(self.itemPictureMain.image!, 0.45)!.writeToFile(fileURL.path!, options: NSDataWritingOptions.AtomicWrite) }catch{ (error) print(error) } self.lastListingKey = newListingRef.key var imageIDs: [String] = [] //post multiple images to fb for i in 0...(self.itemListingDictionary["pictures"] as! [UIImageView]).count - 1 { var parameters: Dictionary = Dictionary() switch (i) { case 0: dispatch_group_enter(fb_group) parameters["Source"] = UIImageJPEGRepresentation(self.itemPictureMain.image!,0.45)! parameters["published"] = false self.graphManager.makePOSTResquest("me/photos", params: parameters, onComplete: { (imageId, error) -> Void in imageIDs.append(imageId as! String) dispatch_group_leave(fb_group) }) break case 1: dispatch_group_enter(fb_group) parameters["Source"] = UIImageJPEGRepresentation(self.itemPictureSup1.image!,0.45)! parameters["published"] = false self.graphManager.makePOSTResquest("me/photos", params: parameters, onComplete: { (imageId, error) -> Void in imageIDs.append(imageId as! String) dispatch_group_leave(fb_group) }) break case 2: dispatch_group_enter(fb_group) parameters["Source"] = UIImageJPEGRepresentation(self.itemPictureSup2.image!,0.45)! parameters["published"] = false self.graphManager.makePOSTResquest("me/photos", params: parameters, onComplete: { (imageId, error) -> Void in imageIDs.append(imageId as! String) dispatch_group_leave(fb_group) }) break case 3: dispatch_group_enter(fb_group) parameters["Source"] = UIImageJPEGRepresentation(self.itemPictureSup3.image!,0.45)! parameters["published"] = false self.graphManager.makePOSTResquest("me/photos", params: parameters, onComplete: { (imageId, error) -> Void in imageIDs.append(imageId as! String) dispatch_group_leave(fb_group) }) break case 4: dispatch_group_enter(fb_group) parameters["Source"] = UIImageJPEGRepresentation(self.itemPictureSup4.image!,0.45)! parameters["published"] = false self.graphManager.makePOSTResquest("me/photos", params: parameters, onComplete: { (imageId, error) -> Void in imageIDs.append(imageId as! String) dispatch_group_leave(fb_group) }) break default: break } } //notifies that all images are ready to be attached to new listing on facebook dispatch_group_notify(fb_group, dispatch_get_main_queue(), { var listingParams: Dictionary = ["message":("**"+self.itemTitle.text!+"**\n\n"+"Price: "+self.itemPrice.text! + "\n\n"+self.itemDescription.text!)] for i in 0...(self.itemListingDictionary["pictures"] as! [UIImageView]).count - 1 { listingParams["attached_media[\(i)]"] = "{\"media_fbid\":\"\(imageIDs[i])\"}" } self.graphManager.makePOSTResquest("me/feed", params: listingParams, onComplete: { (listingId, error) -> Void in if((self.newInProgressListing["networkIDs"] == nil)){ self.newInProgressListing["networkIDs"] = Dictionary() } var networkIDs = (self.newInProgressListing["networkIDs"] as! Dictionary) networkIDs["facebook"] = listingId as! String self.newInProgressListing["networkIDs"] = networkIDs dispatch_group_leave(postingGroup) }) }) } //notifies once all selected networks have been posted to dispatch_group_notify(postingGroup, dispatch_get_main_queue(), { self.newInProgressListing.update(["listingID": newListingRef.key, "seller email": (NSUserDefaults.standardUserDefaults().objectForKey("email") as? String)!, "listingTitle": self.itemTitle.text, "listingPrice": self.itemPrice.text, "listingCategory": self.itemCategory.text, "listingQuantity": self.itemQuantity.text, "listingDescription": self.itemDescription.text, "numberOfSupportingImages" : ((self.itemListingDictionary["pictures"] as? [UIImageView])?.count)! - 1, "isListingDraft": false, "networks": self.networksDictionary]) self.firManager.ref.observeSingleEventOfType(.Value, withBlock: { snapshot in let databaseDict = snapshot.value as! [String : AnyObject] let storageRef = self.firManager.storage.referenceForURL((databaseDict["image_storage"] as? String)!) var imageURLs: [String] = [] let completion: ServiceResponse = {(metadata, error) -> Void in if (error == nil) { //for ebay due to its unique posting flow, will use firbase image storage url to add pictures if (self.networksDictionary["ebay"]!){ print((metadata?.downloadURL()?.absoluteString)!) imageURLs.append((metadata?.downloadURL()?.absoluteString)!) dispatch_group_leave(postingGroup) }else{ dispatch_group_leave(postingGroup) } }else { let alert = UIAlertController(title: "A Problem Occurred", message: "Your listing was submitted to all networks except ebay, due to server side errors. This listing will not be tracked by Vendoo, and must be done manually. Please contact our support team about this issue.", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in self.cancel(self) alert.dismissViewControllerAnimated(true, completion: nil) })) self.presentViewController(alert, animated: true, completion: nil) } } //save listing images to firebase for i in 0...(self.itemListingDictionary["pictures"] as! [UIImageView]).count - 1 { switch (i) { case 0: dispatch_group_enter(postingGroup) let listingImageRef = storageRef.child("images/\(newListingRef.key)/main"+".jpg") self.saveToFirebase(listingImageRef, completion: completion, index: 0) break case 1: dispatch_group_enter(postingGroup) let listingImageRef = storageRef.child("images/\(newListingRef.key)/1"+".jpg") self.saveToFirebase(listingImageRef, completion: completion, index: 1) break case 2: dispatch_group_enter(postingGroup) let listingImageRef = storageRef.child("images/\(newListingRef.key)/2"+".jpg") self.saveToFirebase(listingImageRef, completion: completion, index: 2) break case 3: dispatch_group_enter(postingGroup) let listingImageRef = storageRef.child("images/\(newListingRef.key)/3"+".jpg") self.saveToFirebase(listingImageRef, completion: completion, index: 3) break case 4: dispatch_group_enter(postingGroup) let listingImageRef = storageRef.child("images/\(newListingRef.key)/4"+".jpg") self.saveToFirebase(listingImageRef, completion: completion, index: 4) break default: break } } //notify to upload multiple ebay photos dispatch_group_notify(postingGroup, dispatch_get_main_queue(), { dispatch_group_enter(postingGroup) if (self.networksDictionary["ebay"]!){ let body: [String: String] = [ "title": self.itemTitle.text, "quantity":self.itemQuantity.text, "description":self.itemDescription.text, "price":self.itemPrice.text, "category_id":self.itemListingDictionary["ebaySubCategoryID"] as! String ] let listingCompletion: ServiceResponse = { (listingID, error) -> Void in if((self.newInProgressListing["networkIDs"] == nil)){ self.newInProgressListing["networkIDs"] = Dictionary() } var networkIDs = (self.newInProgressListing["networkIDs"] as! Dictionary) networkIDs["ebay"] = listingID as! String self.newInProgressListing["networkIDs"] = networkIDs dispatch_group_leave(postingGroup) } self.ebayManager.listItem(body, imageUrls: imageURLs, completion: listingCompletion) } else { dispatch_group_leave(postingGroup) } //notify to save final listing to firebase dispatch_group_notify(postingGroup, dispatch_get_main_queue(), { newListingRef.setValue(self.newInProgressListing) //register new listing id in global path of firebase root' self.firManager.ref.child("Global_listings").child(newListingRef.key).setValue(newListingRef.key) self.firManager.indicator.stopAnimating() let alert = UIAlertController(title: "Listing Posted Successfully", message: "Your listing was submitted to all networks successfully", preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:{(action: UIAlertAction!) in self.cancel(self) alert.dismissViewControllerAnimated(true, completion: nil) })) self.presentViewController(alert, animated: true, completion: nil) }) }) }) }) } } @IBAction func editListing(sender: AnyObject) { self.performSegueWithIdentifier("EditListingSegue", sender: self) } } extension ListingPreviewViewController: UICollectionViewDelegate { } //Mark: - UICollectionViewDataSource methods //need to dynamically show, hide, and rearrange the network cells based on users choice of networks extension ListingPreviewViewController: UICollectionViewDataSource { func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of items return self.selectedNetworks.count } //used for displaying relevant networks in listing preview func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell: NetworkCollectionViewCell! = self.networks.dequeueReusableCellWithReuseIdentifier("network", forIndexPath: indexPath) as! NetworkCollectionViewCell cell.setImg(selectedNetworks[indexPath.row]) return cell } }