             }
             else {
                 
-                UIView.animate(withDuration: 0.15, animations: { self.resetLayout() }) 
-            }
-        }
-    }
-    
-    fileprivate var previousViewDisabled: Bool {
-        
-        if !self.configuration.appearance.pastDatesEnabled {
-            
-            if self.previousView.isKind(of: GCCalendarMonthView.self) {
-                
-                return self.currentMonthView.containsToday
-            }
-            else {
-                
-                return self.currentWeekView.containsToday
-            }
-        }
-        
-        return false
-    }
-    
-    // MARK: Show View
+                UIView.animate(withDuration: 0.15, animations: { self.resetLayout() })
+            }
+        }
+    }
     
     fileprivate func showPreviousView() {
         

    }
}

// MARK: - Month & Week Views

public extension GCCalendarView {
    
    // MARK: Views
    

    }
}

// 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 {
