<commit_before>import EurofurenceKit
import SwiftUI

struct ScheduleCollectionView: View {
    
    @EnvironmentObject var model: EurofurenceModel
    @ObservedObject var schedule: ScheduleController
    @State private var isPresentingFilter = false
    
    var body: some View {
        List {
            ForEach(schedule.eventGroups) { group in
                Section {
                    ForEach(group.elements) { (event) in
                        NavigationLink(event.title) {
                            Text(event.title)
                        }
                    }
                } header: {
                    switch group.id {
                    case .startDate(let date):
                        Text(date, format: Date.FormatStyle(date: .omitted, time: .shortened))
                        
                    case .day(let day):
                        Text(verbatim: day.name)
                    }
                }
            }
        }
        .listStyle(.plain)
        .toolbar {
            ToolbarItem(placement: .status) {
                statusView
            }
            
            ToolbarItem(placement: .bottomBar) {
                ScheduleFilterButton(isPresentingFilter: $isPresentingFilter, schedule: schedule)
            }
        }
    }
    
    @ViewBuilder
    private var statusView: some View {
        VStack {
            Text(
                "\(schedule.matchingEventsCount) matching events",
                comment: "Format for presenting the number of matching events in a schedule"
            )
            .font(.caption)
            
            if let localizedFilterDescription = schedule.localizedFilterDescription {
                Text(verbatim: localizedFilterDescription)
                    .font(.caption2)
            }
        }
    }
    
}

private struct ScheduleFilterButton: View {
    
    @Binding var isPresentingFilter: Bool
    var schedule: ScheduleController
    
    var body: some View {
        Button {
            isPresentingFilter.toggle()
        } label: {
            Label {
                Text("Filter")
            } icon: {
                if isPresentingFilter {
                    Image(systemName: "line.3.horizontal.decrease.circle.fill")
                } else {
                    Image(systemName: "line.3.horizontal.decrease.circle")
                }
            }
        }
        .popover(isPresented: $isPresentingFilter) {
            NavigationView {
                ScheduleFilterView(schedule: schedule)
            }
            .sensiblePopoverFrame()
        }
        .enablingMediumPresentationDetent()
    }
    
}

private struct ScheduleFilterView: View {
    
    @ObservedObject var schedule: ScheduleController
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        List {
            if schedule.availableDays.isEmpty == false {
                Section {
                    ScheduleDayPicker(schedule: schedule)
                } header: {
                    Text("Day")
                }
            }
            
            if schedule.availableTracks.isEmpty == false {
                Section {
                    ScheduleTrackPicker(schedule: schedule)
                } header: {
                    Text("Track")
                }
            }
            
            if schedule.availableRooms.isEmpty == false {
                Section {
                    ScheduleRoomPicker(schedule: schedule)
                } header: {
                    Text("Room")
                }
            }
        }
        .listStyle(.insetGrouped)
        .navigationTitle("Filters")
        .toolbar {
            ToolbarItem(placement: .confirmationAction) {
                Button {
                    dismiss()
                } label: {
                    Text("Done")
                }
            }
        }
    }
    
}

private struct ScheduleDayPicker: View {
    
    @ObservedObject var schedule: ScheduleController
    
    var body: some View {
        ForEach(schedule.availableDays) { day in
            SelectableRow(tag: day, selection: $schedule.selectedDay.animation()) {
                DayLabel(day: day, isSelected: schedule.selectedDay == day)
            }
        }
    }
    
}

private struct ScheduleTrackPicker: View {
    
    @ObservedObject var schedule: ScheduleController<commit_msg>Enable filtering to entire convention<commit_after>import EurofurenceKit
import SwiftUI

struct ScheduleCollectionView: View {
    
    @EnvironmentObject var model: EurofurenceModel
    @ObservedObject var schedule: ScheduleController
    @State private var isPresentingFilter = false
    
    var body: some View {
        List {
            ForEach(schedule.eventGroups) { group in
                Section {
                    ForEach(group.elements) { (event) in
                        NavigationLink(event.title) {
                            Text(event.title)
                        }
                    }
                } header: {
                    switch group.id {
                    case .startDate(let date):
                        Text(date, format: Date.FormatStyle(date: .omitted, time: .shortened))
                        
                    case .day(let day):
                        Text(verbatim: day.name)
                    }
                }
            }
        }
        .listStyle(.plain)
        .toolbar {
            ToolbarItem(placement: .status) {
                statusView
            }
            
            ToolbarItem(placement: .bottomBar) {
                ScheduleFilterButton(isPresentingFilter: $isPresentingFilter, schedule: schedule)
            }
        }
    }
    
    @ViewBuilder
    private var statusView: some View {
        VStack {
            Text(
                "\(schedule.matchingEventsCount) matching events",
                comment: "Format for presenting the number of matching events in a schedule"
            )
            .font(.caption)
            
            if let localizedFilterDescription = schedule.localizedFilterDescription {
                Text(verbatim: localizedFilterDescription)
                    .font(.caption2)
            }
        }
    }
    
}

private struct ScheduleFilterButton: View {
    
    @Binding var isPresentingFilter: Bool
    var schedule: ScheduleController
    
    var body: some View {
        Button {
            isPresentingFilter.toggle()
        } label: {
            Label {
                Text("Filter")
            } icon: {
                if isPresentingFilter {
                    Image(systemName: "line.3.horizontal.decrease.circle.fill")
                } else {
                    Image(systemName: "line.3.horizontal.decrease.circle")
                }
            }
        }
        .popover(isPresented: $isPresentingFilter) {
            NavigationView {
                ScheduleFilterView(schedule: schedule)
            }
            .sensiblePopoverFrame()
        }
        .enablingMediumPresentationDetent()
    }
    
}

private struct ScheduleFilterView: View {
    
    @ObservedObject var schedule: ScheduleController
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        List {
            if schedule.availableDays.isEmpty == false {
                Section {
                    ScheduleDayPicker(schedule: schedule)
                } header: {
                    Text("Day")
                }
            }
            
            if schedule.availableTracks.isEmpty == false {
                Section {
                    ScheduleTrackPicker(schedule: schedule)
                } header: {
                    Text("Track")
                }
            }
            
            if schedule.availableRooms.isEmpty == false {
                Section {
                    ScheduleRoomPicker(schedule: schedule)
                } header: {
                    Text("Room")
                }
            }
        }
        .listStyle(.insetGrouped)
        .navigationTitle("Filters")
        .toolbar {
            ToolbarItem(placement: .confirmationAction) {
                Button {
                    dismiss()
                } label: {
                    Text("Done")
                }
            }
        }
    }
    
}

private struct ScheduleDayPicker: View {
    
    @ObservedObject var schedule: ScheduleController
    
    var body: some View {
        SelectableRow(tag: nil, selection: $schedule.selectedDay.animation()) {
            Label {
                Text("Entire Convention")
            } icon: {
                if schedule.selectedTrack == nil {
                    Image(systemName: "calendar.circle.fill")
                } else {
                    Image(systemName: "calendar.circle")
                }
            }
        }
        
        ForEach(schedule.availableDays) { day in
            SelectableRow(tag: day, selection: $schedule.selectedDay.animation()) {
                DayLabel(day: day, isSelected: schedule.selectedDay == day)
            }
        }
    }
    
}

private struct ScheduleTrackPicker: View {
    
    @ObservedObject var schedule: ScheduleController
{'fraction_non_alphanumeric': 0.07584635416666667, 'fraction_numerical': 0.0006510416666666666, 'mean_word_length': 1.2182912154031287, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3108979', 'n_tokens_mistral': 2231, 'n_tokens_neox': 2083, 'n_words': 439}