     }
 }
 
+// MARK: - Today
+
+fileprivate extension GCCalendarView {
+    
+    fileprivate func findTodayInWeekViews() {
+        
+        if self.previousWeekView.containsToday {
+            
+            UIView.animate(withDuration: 0.15, animations: self.showPreviousView, completion: self.previousWeekViewDidShow)
+        }
+        else if self.currentWeekView.containsToday {
+            
+            let todayComponents = self.configuration.calendar.dateComponents([.weekday, .weekOfYear], from: Date())
+            
+            self.currentWeekView.setSelectedDate(weekday: todayComponents.weekday!)
+        }
+        else if self.nextWeekView.containsToday {
+            
+            UIView.animate(withDuration: 0.15, animations: self.showNextView, completion: self.nextWeekViewDidShow)
+        }
+        else {
+            
+            let today = Date()
+            
+            if today.compare(self.selectedDate) == .orderedAscending {
+                
+                self.show(today: today, animations: self.showPreviousView, weekViewReuse: self.reuseNextWeekView) { finished in
+                 
+                    if finished {
+                        
+                        self.previousWeekViewDidShow(finished)
+                        
+                        let newDates = self.nextWeekDates(currentWeekDates: self.currentWeekView.dates)
+                        
+                        self.nextWeekView.dates = newDates
+                    }
+                }
+            }
+            else if today.compare(self.selectedDate) == .orderedDescending {
+                
+                self.show(today: today, animations: self.showNextView, weekViewReuse: self.reusePreviousWeekView) { finished in
+                    
+                    if finished {
+                        
+                        self.nextWeekViewDidShow(finished)
+                        
+                        let newDates = self.previousWeekDates(currentWeekDates: self.currentWeekView.dates)
+                        
+                        self.previousWeekView.dates = newDates
+                    }
+                }
+            }
+        }
+    }
+    
+    fileprivate func show(today: Date, animations: @escaping () -> Void, weekViewReuse: @escaping (([Date?]) -> Void), completion: @escaping ((Bool) -> Void)) {
+        
+        UIView.animate(withDuration: 0.08, animations: animations, completion: { finished in
+            
+            if finished {
+                
+                let newDates = self.currentWeekDates(fromDate: today)
+                
+                weekViewReuse(newDates)
+                
+                self.resetLayout()
+                
+                UIView.animate(withDuration: 0.08, animations: animations, completion: { finished in completion(finished) }) 
+            }
+        }) 
+    }
+    
+    fileprivate func findTodayInMonthViews() {
+        
+        if self.previousMonthView.containsToday {
+            
+            UIView.animate(withDuration: 0.15, animations: self.showPreviousView, completion: self.previousMonthViewDidShow)
+        }
+        else if self.currentMonthView.containsToday {
+            
+            self.currentMonthView.setSelectedDate()
+        }
+        else if self.nextMonthView.containsToday {
+            
+            UIView.animate(withDuration: 0.15, animations: self.showNextView, completion: self.nextMonthViewDidShow)
+        }
+        else {
+            
+            let today = Date()
+            
+            if today.compare(self.selectedDate) == .orderedAscending {
+                
+                self.show(today: today, animations: self.showPreviousView, monthViewReuse: self.reuseNextMonthView) { finished in
+                    
+                    if finished {
+                        
+                        self.previousMonthViewDidShow(finished)
+                        
+                        let newStartDate = self.nextMonthStartDate(currentMonthStartDate: self.currentMonthView.startDate)
+                        
+                        self.nextMonthView.startDate = newStartDate
+                    }
+                }
+            }
+            else if today.compare(self.selectedDate) == .orderedDescending {
+                
+                self.show(today: today, animations: self.showNextView, monthViewReuse: self.reusePreviousMonthView) { finished in
+                    
+                    if finished {
+                        
+                        self.nextMonthViewDidShow(finished)
+                        
+                        let newStartDate = self.previousMonthStartDate(currentMonthStartDate: self.currentMonthView.startDate)
+                        
+                        self.previousMonthView.startDate = newStartDate
+                    }
+                }
+            }
+        }
+    }
+    
+    fileprivate func show(today: Date, animations: @escaping () -> Void, monthViewReuse: @escaping ((Date) -> Void), completion: @escaping ((Bool) -> Void)) {
+        
+        UIView.animate(withDuration: 0.08, animations: animations, completion: { finished in
+            
+            if finished {
+                
+                let newStartDate = self.currentMonthStartDate(fromDate: today)
+                
+                monthViewReuse(newStartDate)
+                
+                self.resetLayout()
+                
+                UIView.animate(withDuration: 0.08, animations: animations, completion: { finished in completion(finished) })
+            }
+        }) 
+    }
+}
+
+// MARK: - Week Views
+
+fileprivate extension GCCalendarView {
+    
+    fileprivate func addWeekViews() {
+        
+        let currentWeekDates = self.currentWeekDates(fromDate: self.selectedDate)
+        let previousWeekDates = self.previousWeekDates(currentWeekDates: currentWeekDates)
+        let nextWeekDates = self.nextWeekDates(currentWeekDates: currentWeekDates)
+        
+        for dates in [previousWeekDates, currentWeekDates, nextWeekDates] {
+            
+            let weekView = GCCalendarWeekView(configuration: self.configuration)
+            
+            weekView.dates = dates
+            weekView.translatesAutoresizingMaskIntoConstraints = false
+            
+            weekView.addPanGestureRecognizer(target: self, action: #selector(self.toggleCurrentView(_:)))
+            
+            self.addSubview(weekView)
+            self.weekViews.append(weekView)
+            
+            weekView.topAnchor.constraint(equalTo: self.headerView.bottomAnchor).isActive = true
+            weekView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
+            weekView.heightAnchor.constraint(equalToConstant: 45).isActive = true
+        }
+        
+        self.resetLayout()
+    }
+    
+    fileprivate func removeWeekViews() {
+        
+        self.weekViews.forEach({ $0.removeFromSuperview() })
+        self.weekViews.removeAll()
+    }
+    
+    // MARK: Views
+    
+    fileprivate var previousWeekView: GCCalendarWeekView {
+        
+        return self.weekViews[0]
+    }
+    
+    fileprivate var currentWeekView: GCCalendarWeekView {
+        
+        return self.weekViews[1]
+    }
+    
+    fileprivate var nextWeekView: GCCalendarWeekView {
+        
+        return self.weekViews[2]
+    }
+    
+    // MARK: Dates
+    
+    fileprivate func previousWeekDates(currentWeekDates: [Date?]) -> [Date?] {
+        
+        let startDate = self.configuration.calendar.date(byAdding: .weekOfYear, value: -1, to: currentWeekDates.first!!)
+        
+        return self.weekDates(startDate: startDate!)
+    }
+    
+    fileprivate func currentWeekDates(fromDate date: Date) -> [Date?] {
+        
+        var components = self.configuration.calendar.dateComponents([.weekday, .weekOfYear, .year], from: date)
+        
+        components.weekday = 1
+        
+        let startDate = self.configuration.calendar.date(from: components)
+        
+        return self.weekDates(startDate: startDate!)
+    }
+    
+    fileprivate func nextWeekDates(currentWeekDates: [Date?]) -> [Date?] {
+        
+        let startDate = self.configuration.calendar.date(byAdding: .weekOfYear, value: 1, to: currentWeekDates.first!!)
+        
+        return self.weekDates(startDate: startDate!)
+    }
+    
+    fileprivate func weekDates(startDate: Date) -> [Date?] {
+        
+        let numberOfWeekdays = self.configuration.calendar.maximumRange(of: .weekday)!.count
+        
+        var dates = [Date?](repeating: nil, count: numberOfWeekdays)
+        
+        var date = startDate
+        
+        repeat {
+            
+            let dateComponents = self.configuration.calendar.dateComponents([.weekday, .weekOfYear, .year], from: date)
+            
+            dates[dateComponents.weekday! - 1] = date
+            
+            date = self.configuration.calendar.date(byAdding: .weekday, value: 1, to: date)!
+            
+        } while self.configuration.calendar.isDate(date, equalTo: startDate, toGranularity: .weekOfYear)
+        
+        return dates
+    }
+    
+    // MARK: Show Week View
+    
+    func previousWeekViewDidShow(_ finished: Bool) {
+        
+        if finished {
+            
+            let newDates = self.previousWeekDates(currentWeekDates: self.previousWeekView.dates)
+            
+            self.reuseNextWeekView(newDates: newDates)
+            
+            self.weekViewDidShow()
+        }
+    }
+    
+    func reuseNextWeekView(newDates: [Date?]) {
+        
+        self.nextWeekView.dates = newDates
+        self.weekViews.insert(self.nextWeekView, at: 0)
+        self.weekViews.removeLast()
+    }
+    
+    func nextWeekViewDidShow(_ finished: Bool) {
+        
+        if finished {
+            
+            let newDates = self.nextWeekDates(currentWeekDates: self.nextWeekView.dates)
+            
+            self.reusePreviousWeekView(newDates: newDates)
+            
+            self.weekViewDidShow()
+        }
+    }
+    
+    func reusePreviousWeekView(newDates: [Date?]) {
+        
+        self.previousWeekView.dates = newDates
+        self.weekViews.append(self.previousWeekView)
+        self.weekViews.removeFirst()
+    }
+    
+    func weekViewDidShow() {
+        
+        self.resetLayout()
+        self.setSelectedWeekViewDate()
+    }
+    
+    // MARK: Selected Week View Date
+    
+    func setSelectedWeekViewDate() {
+        
+        let todayComponents = self.configuration.calendar.dateComponents([.weekday, .weekOfYear], from: Date())
+        
+        if self.configuration.calendar.isDate(self.currentWeekView.dates.first!!, equalTo: Date(), toGranularity: .weekOfYear) {
+            
+            self.currentWeekView.setSelectedDate(weekday: todayComponents.weekday!)
+        }
+        else
+        {
+            let weekday = self.configuration.calendar.dateComponents([.weekday], from: self.selectedDate).weekday
+            
+            self.currentWeekView.setSelectedDate(weekday: weekday!)
+        }
+    }
+}
+
 // MARK: - Month Views
 
 private extension GCCalendarView {

    }
}

// MARK: - Month & Week Views

public extension GCCalendarView {
    
    // MARK: Views
    

            }
            else {
                
                UIView.animate(withDuration: 0.15, animations: { self.resetLayout() })
            }
        }
    }
    
    fileprivate func showPreviousView() {
        
