 import Foundation
 import StoreKit
 
-public typealias RestoreTransactionsCompletionBlock = NSError? -> Void
-public typealias LoadProductsCompletionBlock = (Array<SKProduct>?, NSError?) -> Void
-public typealias PurchaseProductCompletionBlock = (NSError?) -> Void
+public typealias RestoreTransactionsCompletionBlock = (Error?) -> Void
+public typealias LoadProductsCompletionBlock = (Array<SKProduct>?, Error?) -> Void
+public typealias PurchaseProductCompletionBlock = (Error?) -> Void
 public typealias LoadProductsRequestInfo = (request: SKProductsRequest, completion: LoadProductsCompletionBlock)
 public typealias PurchaseProductRequestInfo = (productId: String, completion: PurchaseProductCompletionBlock)
 
 public class IAPManager: NSObject {
-    public static let sharedManager = IAPManager()
+    public static let shared = IAPManager()
     
     override init() {
         super.init()
         
         restorePurchasedItems()
         
-        SKPaymentQueue.defaultQueue().addTransactionObserver(self)
-        
-        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("savePurchasedItems"), name: UIApplicationDidEnterBackgroundNotification, object: nil)
+        SKPaymentQueue.default().add(self)
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(IAPManager.savePurchasedItems), name: NSNotification.Name.UIApplicationDidEnterBackground, object: nil)
     }
     
     public func canMakePayments() -> Bool {

        }
    }
    
    private func callPurchaseProductCompletionForProduct(productId: String, error: NSError?) {
        dispatch_async(dispatch_get_main_queue()) {
            for i in 0..<self.purchaseProductRequests.count {
                let requestInfo = self.purchaseProductRequests[i]
                if requestInfo.productId == productId {
                    self.purchaseProductRequests.removeAtIndex(i)
                    requestInfo.completion(error)
                    return
                }

        request.start()
    }
    
    public func purchaseProduct(productId: String, completion: @escaping PurchaseProductCompletionBlock) {
        if !canMakePayments() {
            let error = NSError(domain: "inapppurchase", code: 0, userInfo: [NSLocalizedDescriptionKey: "In App Purchasing is unavailable"])
            completion(error)
        } else {
            loadProducts(productIds: [productId]) { (products, error) -> Void in
                if error != nil {
                    completion(error)
                } else {
                    if let product = products?.first {
                        self.purchaseProduct(product: product, completion: completion)
                    }
                }
            }
        }
    }
     
    public func purchaseProduct(product: SKProduct, completion: @escaping PurchaseProductCompletionBlock) {
        purchaseProductRequests.append(PurchaseProductRequestInfo(productId: product.productIdentifier, completion: completion))
        let payment = SKPayment(product: product)
        SKPaymentQueue.default().add(payment)
    }
    
    fileprivate func callLoadProductsCompletion(request: SKProductsRequest, responseProducts:Array<SKProduct>?, error: Error?) {
        DispatchQueue.main.async {
            for i in 0..<self.loadProductsRequests.count {
                let requestInfo = self.loadProductsRequests[i]
                if requestInfo.request == request {
                    self.loadProductsRequests.remove(at: i)
                    requestInfo.completion(responseProducts, error)
                    return
                }
