//
//  SettingsView.swift
//  NetNewsWire-iOS
//
//  Created by Maurice Parker on 6/11/19.
//  Copyright © 2019 Ranchero Software. All rights reserved.
//

import SwiftUI
import Combine
import Account

struct SettingsView : View {
	
	@ObservedObject var viewModel: ViewModel

	@Environment(\.viewController) private var viewController: UIViewController?
	@Environment(\.sceneCoordinator) private var coordinator: SceneCoordinator?

	@State private var accountAction: Int? = nil
	@State private var refreshAction: Int? = nil
	@State private var aboutAction: Int? = nil

	@State private var isWebsitePresented: Bool = false
	@State private var website: String? = nil
	
	@State private var isOPMLImportPresented: Bool = false
	@State private var isOPMLImportDocPickerPresented: Bool = false
	@State private var isOPMLExportPresented: Bool = false
	@State private var isOPMLExportDocPickerPresented: Bool = false
	@State private var opmlAccount: Account? = nil

    var body: some View {
		NavigationView {
			Form {
				buildAccountsSection()
				buildTimelineSection()
				buildDatabaseSection()
				buildAboutSection()
			}
			.buttonStyle(VibrantButtonStyle(alignment: .leading))
			.navigationBarTitle(Text("Settings"), displayMode: .inline)
			.navigationBarItems(leading: Button(action: { self.viewController?.dismiss(animated: true) }) { Text("Done") } )
		}
    }
	
	func buildAccountsSection() -> some View {
		Section(header: Text("ACCOUNTS").padding(.top, 22.0)) {
			ForEach(viewModel.accounts.indices, id: \.self) { index in
				NavigationLink(destination: SettingsDetailAccountView(viewModel: SettingsDetailAccountView.ViewModel(self.viewModel.accounts[index])), tag: index, selection: self.$accountAction) {
					Text(verbatim: self.viewModel.accounts[index].nameForDisplay)
				}
				.modifier(VibrantSelectAction(action: {
					self.accountAction = index
				}))
			}
			NavigationLink(destination: SettingsAddAccountView(), tag: 1000, selection: $accountAction) {
				Text("Add Account")
			}
			.modifier(VibrantSelectAction(action: {
				self.accountAction = 1000
			}))
		}
	}
	
	func buildTimelineSection() -> some View {
		Section(header: Text("TIMELINE")) {
			Toggle(isOn: $viewModel.sortOldestToNewest) {
				Text("Sort Newest to Oldest")
			}
			Toggle(isOn: $viewModel.groupByFeed) {
				Text("Group By Feed")
			}
			Stepper(value: $viewModel.timelineNumberOfLines, in: 2...6) {
				Text("Number of Text Lines: \(viewModel.timelineNumberOfLines)")
			}
		}
	}
	
	func buildDatabaseSection() -> some View {
		Section(header: Text("DATABASE")) {

			NavigationLink(destination: SettingsRefreshSelectionView(selectedInterval: $viewModel.refreshInterval), tag: 1, selection: $refreshAction) {
				HStack {
					Text("Refresh Interval")
					Spacer()
					Text(verbatim: self.viewModel.refreshInterval.description()).foregroundColor(.secondary)
				}
			}
			.modifier(VibrantSelectAction(action: {
				self.refreshAction = 1
			}))
			
			Button("Import Subscriptions...") {
				if AccountManager.shared.activeAccounts.count == 1 {
					self.opmlAccount = AccountManager.shared.activeAccounts.first
					self.isOPMLImportDocPickerPresented = true
				} else {
					self.isOPMLImportPresented = true
				}
			}.actionSheet(isPresented: $isOPMLImportPresented) {
				buildSubscriptionsImportAccounts()
			}.sheet(isPresented: $isOPMLImportDocPickerPresented) {
				SettingsSubscriptionsImportDocumentPickerView(account: self.opmlAccount!)
			}
			
			 Button("Export Subscriptions...") {
				if AccountManager.shared.accounts.count == 1 {
					self.opmlAccount = AccountManager.shared.accounts.first
					self.isOPMLImportDocPickerPresented = true
				} else {
					self.isOPMLExportPresented = true
				}
			 }.actionSheet(isPresented: $isOPMLExportPresented) {
				buildSubscriptionsExportAccounts()
			 }.sheet(isPresented: $isOPMLExportDocPickerPresented) {
				 SettingsSubscriptionsExportDocumentPickerView(account: self.opmlAccount!)
			 }
		}
	}
	
	func buildAboutSection() -> some View {
		Section(header: Text("ABOUT"), footer: buildFooter()) {

			NavigationLink(destination: SettingsAboutView(viewModel: SettingsAboutView.ViewModel()), tag: 1, selection: $aboutAction) {
				Text("About NetNewsWire")
			}
			.modifier(VibrantSelectAction(action: {
				self.aboutAction = 1
			}))
			
			Button(action: {
				self.isWebsitePresented.toggle()
				self.website = "https://ranchero.com/netnewswire/"
			}) {
				Text("Website")
			}
			
			Button(action: {
				self.isWebsitePresented.toggle()
				self.website = "https://github.com/brentsimmons/NetNewsWire"
			}) {
				Text("Github Repository")
			}
			
			Button(action: {
				self.isWebsitePresented.toggle()
				self.website = "https://github.com/brentsimmons/NetNewsWire/issues"
			}) {
				Text("Bug Tracker")
			}
			
			Button(action: {
				self.isWebsitePresented.toggle()
				self.website = "https://github.com/brentsimmons/NetNewsWire/tree/master/Technotes"
			}) {
				Text("Technotes")
			}
			
			Button(action: {
				self.isWebsitePresented.toggle()
				self.website = "https://github.com/brentsimmons/NetNewsWire/blob/master/Technotes/HowToSupportNetNewsWire.markdown"
			}) {
				Text("How To Support NetNewsWire")
			}

			if !AccountManager.shared.anyAccountHasFeedWithURL("https://nnw.ranchero.com/feed.json") {
				Button(action: {
					self.viewController?.dismiss(animated: true) {
						let feedName = NSLocalizedString("NetNewsWire News", comment: "NetNewsWire News")
						self.coordinator?.showAdd(.feed, initialFeed: "https://nnw.ranchero.com/feed.json", initialFeedName: feedName)
					}
				}) {
					Text("Add NetNewsWire News Feed")
				}
			}
			
		}.sheet(isPresented: $isWebsitePresented) {
			SafariView(url: URL(string: self.website!)!)
		}
	}
	
	func buildSubscriptionsImportAccounts() -> ActionSheet {
		var buttons = [ActionSheet.Button]()
		
		for account in viewModel.activeAccounts {
			if account.behaviors.contains(.disallowOPMLImports) {
				continue
			}
			
			let button = ActionSheet.Button.default(Text(verbatim: account.nameForDisplay)) {
				self.opmlAccount = account
				self.isOPMLImportDocPickerPresented = true
			}
			
			buttons.append(button)
		}
		
		buttons.append(.cancel())
		return ActionSheet(title: Text("Import Subscriptions..."), message: Text("Select the account to import your OPML file into."), buttons: buttons)
	}
	
	func buildSubscriptionsExportAccounts() -> ActionSheet {
		var buttons = [ActionSheet.Button]()
		
		for account in viewModel.accounts {
			let button = ActionSheet.Button.default(Text(verbatim: account.nameForDisplay)) {
				self.opmlAccount = account
				self.isOPMLExportDocPickerPresented = true
			}
			buttons.append(button)
		}
		
		buttons.append(.cancel())
		return ActionSheet(title: Text("Export Subscriptions..."), message: Text("Select the account to export out of."), buttons: buttons)
	}
	
	func buildFooter() -> some View {
		return Text(verbatim: "\(Bundle.main.appName) v \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))")
			.font(.footnote)
			.foregroundColor(.secondary)
	}
	
	// MARK: ViewModel
	
	class ViewModel: ObservableObject {
		
		let objectWillChange = ObservableObjectPublisher()
		
		init() {
			NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .UserDidAddAccount, object: nil)
			NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange(_:)), name: .UserDidDeleteAccount, object: nil)
			NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange(_:)), name: .DisplayNameDidChange, object: nil)
		}
		
		var accounts: [Account] {
			get {
				return AccountManager.shared.sortedAccounts
			}
			set {
			}
		}
		
		var activeAccounts: [Account] {
			get {
				return AccountManager.shared.sortedActiveAccounts
			}
			set {
			}
		}
		
		var sortOldestToNewest: Bool {
			get {
				return AppDefaults.timelineSortDirection == .orderedDescending
			}
			set {
				objectWillChange.send()
				if newValue == true {
					AppDefaults.timelineSortDirection = .orderedDescending
				} else {
					AppDefaults.timelineSortDirection = .orderedAscending
				}
			}
		}
		
		var groupByFeed: Bool {
			get {
				return AppDefaults.timelineGroupByFeed
			}
			set {
				objectWillChange.send()
				AppDefaults.timelineGroupByFeed = newValue
			}
		}
		
		var timelineNumberOfLines: Int {
			get {
				return AppDefaults.timelineNumberOfLines
			}
			set {
				objectWillChange.send()
				AppDefaults.timelineNumberOfLines = newValue
			}
		}
		
		var refreshInterval: RefreshInterval {
			get {
				return AppDefaults.refreshInterval
			}
			set {
				objectWillChange.send()
				AppDefaults.refreshInterval = newValue
			}
		}
		
		@objc func accountsDidChange(_ notification: Notification) {
			objectWillChange.send()
		}
		
		@objc func displayNameDidChange(_ notification: Notification) {
			objectWillChange.send()
		}
		
	}

}

#if DEBUG
struct SettingsView_Previews : PreviewProvider {
    static var previews: some View {
        SettingsView(viewModel: SettingsView.ViewModel())
    }
}
#endif