import SwiftUI
import SFSafeSymbols

/**
    **Content**
 - iPhone Backgrounds: Add page, html
 - CV: Update PDF

    **UI**
 - Image search: Add view to see all images and filter
 - Page Content: Show all results of `PageGenerationResults`
 - Files: Show usages of file
 - Buttons to insert special commands (images, page links, ...)

    **Features**
 - Posts: Generate separate pages for posts to link to
 - Settings: Introduce `Authors` (`name`, `image`, `description`)
 - Page: Property `author`
 - Blocks: Convert more commands to blocks
 - Graphs, Map, GPX for hikes

    **Generation**
 - Consistency: Check output folder for unused files
 - Empty properties: Show warnings for empty link previews, etc.

    **Fixes**
 - Files: Id change: Check all page contents for links to the renamed file and replace occurences
 - Database: Show errors during loading
 - Mock content: Clean and improve
 - Investigate issue with spaces in content file names
 - Check assignment of blog posts to tags
 */

@main
struct MainView: App {

    private let sidebarWidth: CGFloat = 250

    private let detailWidth: CGFloat = 300

    @StateObject
    private var content: Content = .init()

    @State
    private var language: ContentLanguage = .english

    @ObservedObject
    private var selection: SelectedContent = .init()

    @State
    private var showAddSheet = false

    @State
    private var showInitialSetupSheet = false

    @State
    private var showLoadErrorSheet = false

    @State
    private var loadErrors: [String] = []

    @ViewBuilder
    var sidebar: some View {
        switch selection.tab {
        case .posts:
            PostListView(selectedPost: $selection.post)
        case .pages:
            PageListView(selectedPage: $selection.page)
        case .tags:
            TagListView(selectedTag: $selection.tag)
        case .files:
            FileListView(selectedFile: $selection.file)
        case .generation:
            SettingsListView(selectedSection: $selection.section)
        }
    }

    @ViewBuilder
    var viewContent: some View {
        switch selection.tab {
        case .posts:
            SelectedContentView<PostContentView>(selected: $selection.post)
        case .pages:
            SelectedContentView<PageContentView>(selected: $selection.page)
        case .tags:
            SelectedContentView<TagContentView>(selected: $selection.tag)
        case .files:
            SelectedContentView<FileContentView>(selected: $selection.file)
        case .generation:
            GenerationContentView(selected: $selection.section)
        }
    }

    @ViewBuilder
    var detail: some View {
        switch selection.tab {
        case .posts:
            SelectedDetailView<PostDetailView>(selected: $selection.post)
        case .pages:
            SelectedDetailView<PageDetailView>(selected: $selection.page)
        case .tags:
            SelectedDetailView<TagDetailView>(selected: $selection.tag)
        case .files:
            SelectedDetailView<FileDetailView>(selected: $selection.file)
        case .generation:
            GenerationDetailView(section: selection.section)
        }
    }

    @ViewBuilder
    var addItemSheet: some View {
        switch selection.tab {
        case .posts:
            AddPostView(selected: $selection.post)
        case .pages:
            AddPageView(selected: $selection.page)
        case .tags:
            AddTagView(selected: $selection.tag)
        case .files:
            AddFileView(selectedFile: $selection.file)
        case .generation:
            Text("Not implemented")
        }
    }

    var body: some Scene {
        WindowGroup {
            NavigationSplitView {
                sidebar
                    .toolbar {
                        ToolbarItem(placement: .navigation) {
                            Picker("", selection: $selection.tab) {
                                Text("Posts").tag(MainViewTab.posts)
                                Text("Pages").tag(MainViewTab.pages)
                                Text("Tags").tag(MainViewTab.tags)
                                Text("Files").tag(MainViewTab.files)
                                Text("Generation").tag(MainViewTab.generation)
                            }.pickerStyle(.segmented)
                        }
                    }
                    .navigationSplitViewColumnWidth(min: sidebarWidth, ideal: sidebarWidth, max: sidebarWidth)
                    .toolbar {
                        ToolbarItem(placement: .primaryAction) {
                            Button(action: { showAddSheet = true }) {
                                Label("Add", systemSymbol: .plus)
                            }
                            .disabled(!selection.tab.canAddItems)
                        }
                    }
            } content: {
                viewContent
            } detail: {
                detail
                    .navigationSplitViewColumnWidth(min: detailWidth, ideal: detailWidth, max: detailWidth)
            }
            .toolbar {
                ToolbarItem(placement: .primaryAction) {
                    Picker("", selection: $language) {
                        Text("English")
                            .tag(ContentLanguage.english)
                        Text("German")
                            .tag(ContentLanguage.german)
                    }.pickerStyle(.segmented)
                }
                ToolbarItem(placement: .primaryAction) {
                    if content.storage.contentScope != nil {
                        Button(action: save) {
                            Text("Save")
                        }
                    } else {
                        Button(action: showInitialSheet) {
                            Text("Setup")
                        }
                        .background(RoundedRectangle(cornerRadius: 8).fill(Color.red))
                    }
                }
            }
            .navigationTitle("")
            .environment(\.language, language)
            .environmentObject(content)
            .environmentObject(selection)
            .onAppear(perform: loadContent)
            .onReceive(Timer.publish(every: 60.0, on: .main, in: .common).autoconnect()) { _ in
                save()
            }
            .sheet(isPresented: $showAddSheet) {
                addItemSheet
                    .environment(\.language, language)
                    .environmentObject(content)
                    .environmentObject(selection)
            }
            .sheet(isPresented: $showInitialSetupSheet) {
                InitialSetupView()
                    .environment(\.language, language)
                    .environmentObject(content)
                    .environmentObject(selection)
            }
            .sheet(isPresented: $showLoadErrorSheet) {
                VStack {
                    Text("Failed to load database")
                        .font(.headline)
                    List(loadErrors, id: \.self) { error in
                        HStack {
                            Text(error)
                            Spacer()
                        }
                    }
                    .frame(minHeight: 200)
                    Button("Dismiss", action: { showLoadErrorSheet = false })
                        .padding()
                }
                .padding()
            }
        }
    }

    private func save() {
        guard content.saveToDisk() else {
            print("Failed to save content")
            #warning("Show error message")
            return
        }
    }

    private func loadContent() {
        guard content.storage.contentScope != nil else {
            showInitialSheet()
            return
        }
        content.loadFromDisk { errors in
            prepareAfterLoad()
            guard !errors.isEmpty else {
                return
            }
            self.loadErrors = errors
            self.showLoadErrorSheet = true
        }
    }

    private func prepareAfterLoad() {
        if selection.post == nil {
            selection.post = content.posts.first
        }
        if selection.page == nil {
            selection.page = content.pages.first
        }
        if selection.tag == nil {
            selection.tag = content.tags.first
        }
        if selection.file == nil {
            selection.file = content.files.first
        }
    }

    private func showInitialSheet() {
        DispatchQueue.main.async {
            selection.section = .folders
            selection.tab = .generation
            showInitialSetupSheet = true
        }
    }
}

