             self.triggerPlaybackStateChanged()
         }
     }
-
+    
     public func pause() {
-        if !isPlayable() {
-            return
-        }
-
+        if !isPlayable { return }
+        
         if self.currentState == .Playing {
             debug("Pausing current item")
             self.player?.pause()

        self.updateMediaInfo()
    }

    public func next() {
        if !isPlayable() {
            return
        }
    
        if hasNextItem {
            self.cleanupCurrentItem()
            self.play(self.currentIndex + 1)
        }
    }
    
    // TODO:
    // Check the repeat
    // Check the shuffle settings
    var hasNextItem: Bool {
        return self.currentIndex < self.dataSource!.twistNumberOfItems() - 1
    }
    
    // Check the repeat
    // Check the shuffle settings
    var hasPreviousItem: Bool {
        return self.currentIndex != 0
    }

    public func previous() {
        if !isPlayable() {
            return
        }

        // TODO:
        // Seek to 0 if time is more than 5 seconds, else go to previous
        if hasPreviousItem {
            self.cleanupCurrentItem()
            self.play(self.currentIndex - 1)
        }
    }

    func isPlayable() -> Bool {
        guard let dataSource = self.dataSource else { return false }
        return dataSource.twistNumberOfItems() > 0
    }

    override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if context == &myContext {
            if let player = self.player where object is AVPlayer {

        }
    }
    
    public func togglePlayPause() {
        if self.currentState == .Playing {
            self.pause()
        } else {
            self.play()
        }
    }

    public func previous() {
        if !isPlayable { return }
        
        // TODO: Seek to 0 if time is more than 5 seconds, else go to previous
        if hasPreviousItem {
            self.cleanupCurrentItem()
            self.play(self.currentIndex - 1)
        }
    }
    
    // MARK: Listeners and events setup
    func configurePlayer() {
        self.preConfigured = true
        self.player = AVPlayer()
        self.registerAudioSession()
        self.registerListeners()
        self.setupRemoteCommandTargets()
    }
    
    func registerListener(selector: Selector, notification: String) {
        NSNotificationCenter.defaultCenter().addObserver(
            self, selector: selector, name: notification, object: nil
        )
    }
    
    func registerListeners() {
        registerListener(#selector(Twist.playerItemDidReachEnd(_:)), notification: AVPlayerItemDidPlayToEndTimeNotification)
        registerListener(#selector(Twist.playerItemFailedToPlayEndTime(_:)), notification: AVPlayerItemFailedToPlayToEndTimeNotification)
        registerListener(#selector(Twist.playerItemPlaybackStall(_:)), notification: AVPlayerItemPlaybackStalledNotification)
        registerListener(#selector(Twist.interruption(_:)), notification: AVAudioSessionInterruptionNotification)
        registerListener(#selector(Twist.routeChange(_:)), notification: AVAudioSessionRouteChangeNotification)
    }
    
    func setupRemoteCommandTargets() {
        let commandCenter = MPRemoteCommandCenter.sharedCommandCenter()
        commandCenter.nextTrackCommand.addTarget(self, action: #selector(Twist.next))
        commandCenter.previousTrackCommand.addTarget(self, action: #selector(Twist.previous))
        commandCenter.playCommand.addTarget(self, action: #selector(Twist.play(_:)))
        commandCenter.pauseCommand.addTarget(self, action: #selector(Twist.pause))
        commandCenter.togglePlayPauseCommand.addTarget(self, action: #selector(Twist.togglePlayPause))
    }
    
    func playerItemDidReachEnd(notification: NSNotification) {
        self.next()
    }
    
    func playerItemFailedToPlayEndTime(notification: NSNotification) {
        self.next()
    }
    
    func playerItemPlaybackStall(notification: NSNotification) {
        debug("playback stalled")
    }
    
    func interruption(notification: NSNotification) {
        if  let notificationType = notification.userInfo?[AVAudioSessionInterruptionTypeKey] as? UInt,
            let interruptionType = AVAudioSessionInterruptionType(rawValue: notificationType) {
            switch interruptionType {
            case .Began:
                self.interruptedWhilePlaying = (self.currentState == .Playing)
                self.pause()
            case .Ended:
                if self.interruptedWhilePlaying {
                    self.interruptedWhilePlaying = false
                    self.play()
                }
            }
        }
    }
    
    func routeChange(notification: NSNotification) {
        if  let notificationType = notification.userInfo?[AVAudioSessionRouteChangeReasonKey] as? UInt,
            let reason = AVAudioSessionRouteChangeReason(rawValue: notificationType) {
            switch reason {
            case .OldDeviceUnavailable:
                self.pause()
                debug("Route changed and paused")
            default:
                debug("Route changed but no need to pause: \(notificationType.description)")
            }
        }
    }
    
    func registerAudioSession() {
        let audioSession = AVAudioSession.sharedInstance()
        UIApplication.sharedApplication().beginReceivingRemoteControlEvents()
        
        if audioSession.category != AVAudioSessionCategoryPlayback {
            let device = UIDevice.currentDevice()
            if device.multitaskingSupported {
                do {
                    try audioSession.setCategory(AVAudioSessionCategoryPlayback)
                } catch let error as NSError {
                    debug("Set Category error: \(error.localizedDescription)")
                }
                do {
                    try audioSession.setActive(true)
                } catch let error as NSError {
                    debug("Set active error: \(error.localizedDescription)")
                }
            }
        } else {
            debug("Unable to register background playback")
        }
    }

    // MARK: Helper methods
    func cleanupCurrentItem() {
        self.currentState = .Waiting
        self.currentPlayerItem?.removeObserver(self, forKeyPath: kStatusKey)
