 
                         let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightImageCellIdentifier, forIndexPath: indexPath) as! ChatRightImageCell
 
-                        cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in
-
-                            if message.sendState == MessageSendState.Failed.rawValue {
-
-                                YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend image?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: {
-
-                                    resendMessage(message, failureHandler: { [weak self] reason, errorMessage in
-                                        defaultFailureHandler(reason, errorMessage)
-
-                                        YepAlert.alertSorry(message: NSLocalizedString("Failed to resend image!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self)
-
-                                    }, completion: { success in
-                                        println("resendImage: \(success)")
-                                    })
-
-                                }, cancelAction: {
-                                })
-
-                            } else {
-                                self?.performSegueWithIdentifier("showMessageMedia", sender: message)
-                            }
-
-                        }, collectionView: collectionView, indexPath: indexPath)
-
-                        cell.tapAvatarAction = { [weak self] user in
-                            self?.performSegueWithIdentifier("showProfile", sender: user)
-                        }
-                        
                         return cell
 
                     case MessageMediaType.Audio.rawValue:
 
                         let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightAudioCellIdentifier, forIndexPath: indexPath) as! ChatRightAudioCell
 
-                        let audioPlayedDuration = audioPlayedDurationOfMessage(message)
-
-                        cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in
-
-                            if message.sendState == MessageSendState.Failed.rawValue {
-
-                                YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend audio?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: {
-
-                                    resendMessage(message, failureHandler: { [weak self] reason, errorMessage in
-                                        defaultFailureHandler(reason, errorMessage)
-
-                                        YepAlert.alertSorry(message: NSLocalizedString("Failed to resend audio!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self)
-
-                                    }, completion: { success in
-                                        println("resendAudio: \(success)")
-                                    })
-
-                                }, cancelAction: {
-                                })
-
-                                return
-                            }
-
-                            self?.playMessageAudioWithMessage(message)
-
-                        }, collectionView: collectionView, indexPath: indexPath)
-
-                        cell.tapAvatarAction = { [weak self] user in
-                            self?.performSegueWithIdentifier("showProfile", sender: user)
-                        }
-
                         return cell
 
                     case MessageMediaType.Video.rawValue:
 
                         let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightVideoCellIdentifier, forIndexPath: indexPath) as! ChatRightVideoCell
 
-                        cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in
-
-                            if message.sendState == MessageSendState.Failed.rawValue {
-
-                                YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend video?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: {
-
-                                    resendMessage(message, failureHandler: { [weak self] reason, errorMessage in
-                                        defaultFailureHandler(reason, errorMessage)
-
-                                        YepAlert.alertSorry(message: NSLocalizedString("Failed to resend video!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self)
-
-                                    }, completion: { success in
-                                        println("resendVideo: \(success)")
-                                    })
-
-                                }, cancelAction: {
-                                })
-
-                            } else {
-                                self?.performSegueWithIdentifier("showMessageMedia", sender: message)
-                            }
-
-                        }, collectionView: collectionView, indexPath: indexPath)
-
-                        cell.tapAvatarAction = { [weak self] user in
-                            self?.performSegueWithIdentifier("showProfile", sender: user)
-                        }
-
                         return cell
 
                     case MessageMediaType.Location.rawValue:
 
                         let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightLocationCellIdentifier, forIndexPath: indexPath) as! ChatRightLocationCell
 
-                        cell.configureWithMessage(message, mediaTapAction: { [weak self] in
-
-                            if message.sendState == MessageSendState.Failed.rawValue {
-
-                                YepAlert.confirmOrCancel(title: NSLocalizedString("Action", comment: ""), message: NSLocalizedString("Resend location?", comment: ""), confirmTitle: NSLocalizedString("Resend", comment: ""), cancelTitle: NSLocalizedString("Cancel", comment: ""), inViewController: self, withConfirmAction: {
-
-                                    resendMessage(message, failureHandler: { [weak self] reason, errorMessage in
-                                        defaultFailureHandler(reason, errorMessage)
-
-                                        YepAlert.alertSorry(message: NSLocalizedString("Failed to resend location!\nPlease make sure your iPhone is connected to the Internet.", comment: ""), inViewController: self)
-
-                                    }, completion: { success in
-                                        println("resendLocation: \(success)")
-                                    })
-
-                                }, cancelAction: {
-                                })
-
-                            } else {
+                        return cell
+
+                    default:
+
+                        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatRightTextCellIdentifier, forIndexPath: indexPath) as! ChatRightTextCell
+
+                        return cell
+                    }
+                }
+            }
+        }
+
+        println("🐌 Conversation: Should not be there")
+
+        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatSectionDateCellIdentifier, forIndexPath: indexPath) as! ChatSectionDateCell
+
+        cell.sectionDateLabel.text = "🐌"
+
+        return cell
+
+    }
+
+    func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
+
+        if let message = messages[safe: (displayedMessagesRange.location + indexPath.item)] {
+
+            if message.mediaType == MessageMediaType.SectionDate.rawValue {
+
+                if let cell = cell as? ChatSectionDateCell {
+                    let createdAt = NSDate(timeIntervalSince1970: message.createdUnixTime)
+
+                    if createdAt.isInCurrentWeek() {
+                        cell.sectionDateLabel.text = sectionDateInCurrentWeekFormatter.stringFromDate(createdAt)
+                    } else {
+                        cell.sectionDateLabel.text = sectionDateFormatter.stringFromDate(createdAt)
+                    }
+                }
+
+                return
+            }
+
+            if let sender = message.fromFriend {
+
+                if sender.friendState != UserFriendState.Me.rawValue { // from Friend
+
+                    markMessageAsReaded(message)
+
+                    switch message.mediaType {
+
+                    case MessageMediaType.Image.rawValue:
+
+                        if let cell = cell as? ChatLeftImageCell {
+
+                            cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in
+
+                                if message.downloadState == MessageDownloadState.Downloaded.rawValue {
+                                    self?.performSegueWithIdentifier("showMessageMedia", sender: message)
+
+                                } else {
+                                    YepAlert.alertSorry(message: NSLocalizedString("Please wait while the image is not dready!", comment: ""), inViewController: self)
+                                }
+
+                            }, collectionView: collectionView, indexPath: indexPath)
+
+                            cell.tapAvatarAction = { [weak self] user in
+                                self?.performSegueWithIdentifier("showProfile", sender: user)
+                            }
+                        }
+
+                    case MessageMediaType.Audio.rawValue:
+
+                        if let cell = cell as? ChatLeftAudioCell {
+
+                            let audioPlayedDuration = audioPlayedDurationOfMessage(message)
+
+                            cell.configureWithMessage(message, audioPlayedDuration: audioPlayedDuration, audioBubbleTapAction: { [weak self] in
+
+                                if message.downloadState == MessageDownloadState.Downloaded.rawValue {
+                                    self?.playMessageAudioWithMessage(message)
+
+                                } else {
+                                    YepAlert.alertSorry(message: NSLocalizedString("Please wait while the audio is not dready!", comment: ""), inViewController: self)
+                                }
+
+                            }, collectionView: collectionView, indexPath: indexPath)
+
+                            cell.tapAvatarAction = { [weak self] user in
+                                self?.performSegueWithIdentifier("showProfile", sender: user)
+                            }
+                        }
+
+                    case MessageMediaType.Video.rawValue:
+
+                        if let cell = cell as? ChatLeftVideoCell {
+
+                            cell.configureWithMessage(message, messageImagePreferredWidth: messageImagePreferredWidth, messageImagePreferredHeight: messageImagePreferredHeight, messageImagePreferredAspectRatio: messageImagePreferredAspectRatio, mediaTapAction: { [weak self] in
+
+                                if message.downloadState == MessageDownloadState.Downloaded.rawValue {
+                                    self?.performSegueWithIdentifier("showMessageMedia", sender: message)
+
+                                } else {
+                                    YepAlert.alertSorry(message: NSLocalizedString("Please wait while the video is not dready!", comment: ""), inViewController: self)
+                                }
+
+                            }, collectionView: collectionView, indexPath: indexPath)
+
+                            cell.tapAvatarAction = { [weak self] user in
+                                self?.performSegueWithIdentifier("showProfile", sender: user)
+                            }
+                        }
+
+
+                    case MessageMediaType.Location.rawValue:
+
+                        if let cell = cell as? ChatLeftLocationCell {
+
+                            cell.configureWithMessage(message, mediaTapAction: { [weak self] in
                                 if let coordinate = message.coordinate {
                                     let locationCoordinate = CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)
                                     let mapItem = MKMapItem(placemark: MKPlacemark(coordinate: locationCoordinate, addressDictionary: nil))


                let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatSectionDateCellIdentifier, forIndexPath: indexPath) as! ChatSectionDateCell

                let createdAt = NSDate(timeIntervalSince1970: message.createdUnixTime)

                if createdAt.isInCurrentWeek() {
                    cell.sectionDateLabel.text = sectionDateInCurrentWeekFormatter.stringFromDate(createdAt)
                } else {
                    cell.sectionDateLabel.text = sectionDateFormatter.stringFromDate(createdAt)
                }

                return cell
            }



                        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftImageCellIdentifier, forIndexPath: indexPath) as! ChatLeftImageCell

                        return cell

                    case MessageMediaType.Audio.rawValue:

                        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftAudioCellIdentifier, forIndexPath: indexPath) as! ChatLeftAudioCell

                        return cell

                    case MessageMediaType.Video.rawValue:

                        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftVideoCellIdentifier, forIndexPath: indexPath) as! ChatLeftVideoCell

                        return cell

                    case MessageMediaType.Location.rawValue:

                        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(chatLeftLocationCellIdentifier, forIndexPath: indexPath) as! ChatLeftLocationCell

                        return cell

                    default:
