import Defaults
import SwiftUI

struct PlayerSettings: View {
    @Default(.instances) private var instances
    @Default(.playerInstanceID) private var playerInstanceID

    @Default(.playerSidebar) private var playerSidebar

    @Default(.showKeywords) private var showKeywords
    #if !os(tvOS)
        @Default(.showScrollToTopInComments) private var showScrollToTopInComments
        @Default(.collapsedLinesDescription) private var collapsedLinesDescription
    #endif
    @Default(.expandVideoDescription) private var expandVideoDescription
    @Default(.pauseOnHidingPlayer) private var pauseOnHidingPlayer
    @Default(.closeVideoOnEOF) private var closeVideoOnEOF
    #if os(iOS)
        @Default(.honorSystemOrientationLock) private var honorSystemOrientationLock
        @Default(.enterFullscreenInLandscape) private var enterFullscreenInLandscape
        @Default(.rotateToLandscapeOnEnterFullScreen) private var rotateToLandscapeOnEnterFullScreen
    #endif
    @Default(.closePiPOnNavigation) private var closePiPOnNavigation
    @Default(.closePiPOnOpeningPlayer) private var closePiPOnOpeningPlayer
    @Default(.closePlayerOnOpeningPiP) private var closePlayerOnOpeningPiP
    #if !os(macOS)
        @Default(.pauseOnEnteringBackground) private var pauseOnEnteringBackground
        @Default(.closePiPAndOpenPlayerOnEnteringForeground) private var closePiPAndOpenPlayerOnEnteringForeground
    #endif

    @Default(.enableReturnYouTubeDislike) private var enableReturnYouTubeDislike

    @Default(.showRelated) private var showRelated
    @Default(.showInspector) private var showInspector

    @Default(.showChapters) private var showChapters
    @Default(.showChapterThumbnails) private var showThumbnails
    @Default(.showChapterThumbnailsOnlyWhenDifferent) private var showThumbnailsOnlyWhenDifferent
    @Default(.expandChapters) private var expandChapters

    @Default(.captionsAutoShow) private var captionsAutoShow
    @Default(.captionsDefaultLanguageCode) private var captionsDefaultLanguageCode
    @Default(.captionsFallbackLanguageCode) private var captionsFallbackLanguageCode
    @Default(.captionsFontScaleSize) private var captionsFontScaleSize
    @Default(.captionsFontColor) private var captionsFontColor

    @ObservedObject private var accounts = AccountsModel.shared

    #if os(iOS)
        private var idiom: UIUserInterfaceIdiom {
            UIDevice.current.userInterfaceIdiom
        }
    #endif

    #if os(tvOS)
        @State private var isShowingDefaultLanguagePicker = false
        @State private var isShowingFallbackLanguagePicker = false
    #endif

    var body: some View {
        Group {
            #if os(macOS)
                sections

                Spacer()
            #else
                List {
                    sections
                }
            #endif
        }
        #if os(tvOS)
        .frame(maxWidth: 1000)
        #elseif os(iOS)
        .listStyle(.insetGrouped)
        #endif
        .navigationTitle("Player")
    }

    private var sections: some View {
        Group {
            Section(header: SettingsHeader(text: "Playback".localized())) {
                if !accounts.isEmpty {
                    sourcePicker
                }
                pauseOnHidingPlayerToggle
                closeVideoOnEOFToggle
                #if !os(macOS)
                    pauseOnEnteringBackgroundToogle
                #endif
            }

            #if !os(tvOS)
                Section(header: SettingsHeader(text: "Info".localized())) {
                    expandVideoDescriptionToggle
                    collapsedLineDescriptionStepper
                    showRelatedToggle
                    #if os(macOS)
                        HStack {
                            Text("Inspector")
                            inspectorVisibilityPicker
                        }
                        .padding(.leading, 20)
                    #else
                        inspectorVisibilityPicker
                    #endif
                }
            #endif

            Section(header: SettingsHeader(text: "Captions".localized())) {
                #if os(tvOS)
                    Text("Size").font(.subheadline)
                #endif
                captionsFontScaleSizePicker
                #if os(tvOS)
                    Text("Color").font(.subheadline)
                #endif
                captionsFontColorPicker
                showCaptionsAutoShowToggle

                #if !os(tvOS)
                    captionDefaultLanguagePicker
                    captionFallbackLanguagePicker
                #else
                    Button(action: { isShowingDefaultLanguagePicker = true }) {
                        HStack {
                            Text("Default language")
                            Spacer()
                            Text("\(LanguageCodes(rawValue: captionsDefaultLanguageCode)!.description.capitalized) (\(captionsDefaultLanguageCode))").foregroundColor(.secondary)
                        }
                    }
                    .frame(maxWidth: .infinity).sheet(isPresented: $isShowingDefaultLanguagePicker) {
                        defaultLanguagePickerTVOS(
                            selectedLanguage: $captionsDefaultLanguageCode,
                            isShowing: $isShowingDefaultLanguagePicker
                        )
                    }

                    Button(action: { isShowingFallbackLanguagePicker = true }) {
                        HStack {
                            Text("Fallback language")
                            Spacer()
                            Text("\(LanguageCodes(rawValue: captionsFallbackLanguageCode)!.description.capitalized) (\(captionsFallbackLanguageCode))").foregroundColor(.secondary)
                        }
                    }
                    .frame(maxWidth: .infinity).sheet(isPresented: $isShowingDefaultLanguagePicker) {
                        fallbackLanguagePickerTVOS(
                            selectedLanguage: $captionsFallbackLanguageCode,
                            isShowing: $isShowingFallbackLanguagePicker
                        )
                    }
                #endif
            }

            #if !os(tvOS)
                Section(header: SettingsHeader(text: "Chapters".localized())) {
                    showChaptersToggle
                    showThumbnailsToggle
                    showThumbnailsWhenDifferentToggle
                    expandChaptersToggle
                }
            #endif

            let interface = Section(header: SettingsHeader(text: "Interface".localized())) {
                #if os(iOS)
                    if idiom == .pad {
                        sidebarPicker
                    }
                #endif

                #if os(macOS)
                    sidebarPicker
                #endif

                if !accounts.isEmpty {
                    keywordsToggle

                    #if !os(tvOS)
                        showScrollToTopInCommentsToggle
                    #endif

                    returnYouTubeDislikeToggle
                }
            }

            #if os(tvOS)
                if !accounts.isEmpty {
                    interface
                }
            #elseif os(macOS)
                interface
            #elseif os(iOS)
                if idiom == .pad || !accounts.isEmpty {
                    interface
                }
            #endif

            #if os(iOS)
                Section(header: SettingsHeader(text: "Orientation".localized())) {
                    if idiom == .pad {
                        enterFullscreenInLandscapeToggle
                    }
                    honorSystemOrientationLockToggle
                    rotateToLandscapeOnEnterFullScreenPicker
                }
            #endif

            Section(header: SettingsHeader(text: "Picture in Picture".localized())) {
                closePiPOnNavigationToggle
                closePiPOnOpeningPlayerToggle
                closePlayerOnOpeningPiPToggle
                #if !os(macOS)
                    closePiPAndOpenPlayerOnEnteringForegroundToggle
                #endif
            }
        }
    }

    private var videoDetailsHeaderPadding: Double {
        #if os(macOS)
            5.0
        #else
            0.0
        #endif
    }

    private var sourcePicker: some View {
        Picker("Source", selection: $playerInstanceID) {
            Text("Instance of current account").tag(String?.none)

            ForEach(instances) { instance in
                Text(instance.description).tag(Optional(instance.id))
            }
        }
        .modifier(SettingsPickerModifier())
    }

    private var sidebarPicker: some View {
        Picker("Sidebar", selection: $playerSidebar) {
            #if os(macOS)
                Text("Show sidebar").tag(PlayerSidebarSetting.always)
            #endif

            #if os(iOS)
                Text("Show sidebar when space permits").tag(PlayerSidebarSetting.whenFits)
            #endif

            Text("Hide sidebar").tag(PlayerSidebarSetting.never)
        }
        .modifier(SettingsPickerModifier())
    }

    #if !os(tvOS)
        private var showScrollToTopInCommentsToggle: some View {
            Toggle("Show scroll to top button in comments", isOn: $showScrollToTopInComments)
        }
    #endif

    private var keywordsToggle: some View {
        Toggle("Show keywords", isOn: $showKeywords)
    }

    private var expandVideoDescriptionToggle: some View {
        Toggle("Open video description expanded", isOn: $expandVideoDescription)
    }

    #if !os(tvOS)
        private var collapsedLineDescriptionStepper: some View {
            LazyVStack {
                Stepper(value: $collapsedLinesDescription, in: 0 ... 10) {
                    Text("Description preview")
                    #if os(macOS)
                        Spacer()
                    #endif
                    if collapsedLinesDescription == 0 {
                        Text("No preview")
                    } else {
                        Text("\(collapsedLinesDescription) lines")
                    }
                }
            }
        }
    #endif

    private var returnYouTubeDislikeToggle: some View {
        Toggle("Enable Return YouTube Dislike", isOn: $enableReturnYouTubeDislike)
    }

    private var pauseOnHidingPlayerToggle: some View {
        Toggle("Pause when player is closed", isOn: $pauseOnHidingPlayer)
    }

    private var closeVideoOnEOFToggle: some View {
        Toggle("Close video and player on end", isOn: $closeVideoOnEOF)
    }

    #if !os(macOS)
        private var pauseOnEnteringBackgroundToogle: some View {
            Toggle("Pause when entering background", isOn: $pauseOnEnteringBackground)
        }
    #endif

    #if os(iOS)
        private var honorSystemOrientationLockToggle: some View {
            Toggle("Honor orientation lock", isOn: $honorSystemOrientationLock)
                .disabled(!enterFullscreenInLandscape)
        }

        private var enterFullscreenInLandscapeToggle: some View {
            Toggle("Enter fullscreen in landscape", isOn: $enterFullscreenInLandscape)
        }

        private var rotateToLandscapeOnEnterFullScreenPicker: some View {
            Picker("Rotate when entering fullscreen on landscape video", selection: $rotateToLandscapeOnEnterFullScreen) {
                Text("Landscape left").tag(FullScreenRotationSetting.landscapeRight)
                Text("Landscape right").tag(FullScreenRotationSetting.landscapeLeft)
                Text("No rotation").tag(FullScreenRotationSetting.disabled)
            }
            .modifier(SettingsPickerModifier())
        }
    #endif

    private var closePiPOnNavigationToggle: some View {
        Toggle("Close PiP when starting playing other video", isOn: $closePiPOnNavigation)
    }

    private var closePiPOnOpeningPlayerToggle: some View {
        Toggle("Close PiP when player is opened", isOn: $closePiPOnOpeningPlayer)
    }

    private var closePlayerOnOpeningPiPToggle: some View {
        Toggle("Close player when starting PiP", isOn: $closePlayerOnOpeningPiP)
    }

    #if !os(macOS)
        private var closePiPAndOpenPlayerOnEnteringForegroundToggle: some View {
            Toggle("Close PiP and open player when application enters foreground", isOn: $closePiPAndOpenPlayerOnEnteringForeground)
        }
    #endif

    private var showCaptionsAutoShowToggle: some View {
        Toggle("Always show captions", isOn: $captionsAutoShow)
    }

    private var captionsFontScaleSizePicker: some View {
        Picker("Size", selection: $captionsFontScaleSize) {
            Text("Small").tag(String("0.5"))
            Text("Medium").tag(String("1.0"))
            Text("Large").tag(String("2.0"))
        }
        .onChange(of: captionsFontScaleSize) { _ in
            PlayerModel.shared.mpvBackend.client.setSubFontSize(scaleSize: captionsFontScaleSize)
        }
        #if os(macOS)
        .labelsHidden()
        #endif
    }

    private var captionsFontColorPicker: some View {
        Picker("Color", selection: $captionsFontColor) {
            Text("White").tag(String("#FFFFFF"))
            Text("Yellow").tag(String("#FFFF00"))
            Text("Red").tag(String("#FF0000"))
            Text("Orange").tag(String("#FFA500"))
            Text("Green").tag(String("#008000"))
            Text("Blue").tag(String("#0000FF"))
        }
        .onChange(of: captionsFontColor) { _ in
            PlayerModel.shared.mpvBackend.client.setSubFontColor(color: captionsFontColor)
        }
        #if os(macOS)
        .labelsHidden()
        #endif
    }

    #if !os(tvOS)
        private var captionDefaultLanguagePicker: some View {
            Picker("Default language", selection: $captionsDefaultLanguageCode) {
                ForEach(LanguageCodes.allCases, id: \.self) { language in
                    Text("\(language.description.capitalized) (\(language.rawValue))").tag(language.rawValue)
                }
            }
            #if os(macOS)
            .labelsHidden()
            #endif
        }

        private var captionFallbackLanguagePicker: some View {
            Picker("Fallback language", selection: $captionsFallbackLanguageCode) {
                ForEach(LanguageCodes.allCases, id: \.self) { language in
                    Text("\(language.description.capitalized) (\(language.rawValue))").tag(language.rawValue)
                }
            }
            #if os(macOS)
            .labelsHidden()
            #endif
        }
    #else
        struct defaultLanguagePickerTVOS: View {
            @Binding var selectedLanguage: String
            @Binding var isShowing: Bool

            var body: some View {
                NavigationView {
                    List(LanguageCodes.allCases, id: \.self) { language in
                        Button(action: {
                            selectedLanguage = language.rawValue
                            isShowing = false
                        }) {
                            Text("\(language.description.capitalized) (\(language.rawValue))")
                        }
                    }
                    .navigationTitle("Select Default Language")
                }
            }
        }

        struct fallbackLanguagePickerTVOS: View {
            @Binding var selectedLanguage: String
            @Binding var isShowing: Bool

            var body: some View {
                NavigationView {
                    List(LanguageCodes.allCases, id: \.self) { language in
                        Button(action: {
                            selectedLanguage = language.rawValue
                            isShowing = false
                        }) {
                            Text("\(language.description.capitalized) (\(language.rawValue))")
                        }
                    }
                    .navigationTitle("Select Fallback Language")
                }
            }
        }
    #endif

    #if !os(tvOS)
        private var inspectorVisibilityPicker: some View {
            Picker("Inspector", selection: $showInspector) {
                Text("Always").tag(ShowInspectorSetting.always)
                Text("Only for local files and URLs").tag(ShowInspectorSetting.onlyLocal)
            }
            #if os(macOS)
            .labelsHidden()
            #endif
        }

        private var showChaptersToggle: some View {
            Toggle("Show chapters", isOn: $showChapters)
        }

        private var showThumbnailsToggle: some View {
            Toggle("Show thumbnails", isOn: $showThumbnails)
                .disabled(!showChapters)
                .foregroundColor(showChapters ? .primary : .secondary)
        }

        private var showThumbnailsWhenDifferentToggle: some View {
            Toggle("Show thumbnails only when unique", isOn: $showThumbnailsOnlyWhenDifferent)
                .disabled(!showChapters || !showThumbnails)
                .foregroundColor(showChapters && showThumbnails ? .primary : .secondary)
        }

        private var expandChaptersToggle: some View {
            Toggle("Open vertical chapters expanded", isOn: $expandChapters)
                .disabled(!showChapters)
                .foregroundColor(showChapters ? .primary : .secondary)
        }

        private var showRelatedToggle: some View {
            Toggle("Related", isOn: $showRelated)
        }
    #endif
}

struct PlayerSettings_Previews: PreviewProvider {
    static var previews: some View {
        VStack(alignment: .leading) {
            PlayerSettings()
        }
        .frame(minHeight: 800)
        .injectFixtureEnvironmentObjects()
    }
}