//
//  TimelineView.swift
//  NetNewsWire
//
//  Created by Maurice Parker on 6/30/20.
//  Copyright © 2020 Ranchero Software. All rights reserved.
//

import SwiftUI

struct TimelineView: View {
	
	@Binding var timelineItems: TimelineItems
	@Binding var isReadFiltered: Bool?

	@EnvironmentObject private var timelineModel: TimelineModel

	@State private var timelineItemFrames = [String: CGRect]()
	
	var body: some View {
		GeometryReader { geometryReaderProxy in
			#if os(macOS)
			VStack {
				HStack {
					TimelineSortOrderView()
					Spacer()
					Button (action: {
						if let filtered = isReadFiltered {
							timelineModel.changeReadFilterSubject.send(!filtered)
						}
					}, label: {
						if isReadFiltered ?? false {
							AppAssets.filterActiveImage
						} else {
							AppAssets.filterInactiveImage
						}
					})
					.hidden(isReadFiltered == nil)
					.padding(.top, 8).padding(.trailing)
					.buttonStyle(PlainButtonStyle())
					.help(isReadFiltered ?? false ? "Show Read Articles" : "Filter Read Articles")
				}
				ScrollViewReader { scrollViewProxy in
					List(timelineItems.items, selection: $timelineModel.selectedTimelineItemIDs) { timelineItem in
						let selected = timelineModel.selectedTimelineItemIDs.contains(timelineItem.article.articleID)
						TimelineItemView(selected: selected, width: geometryReaderProxy.size.width, timelineItem: timelineItem)
							.background(TimelineItemFramePreferenceView(timelineItem: timelineItem))
					}
					.id(timelineModel.listID)
					.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
						for pref in preferences {
							timelineItemFrames[pref.articleID] = pref.frame
						}
					}
					.onChange(of: timelineModel.selectedTimelineItemIDs) { selectedArticleIDs in
						let proxyFrame = geometryReaderProxy.frame(in: .global)
						for articleID in selectedArticleIDs {
							if let itemFrame = timelineItemFrames[articleID] {
								if itemFrame.minY < proxyFrame.minY + 3 || itemFrame.maxY > proxyFrame.maxY - 35 {
									withAnimation {
										scrollViewProxy.scrollTo(articleID, anchor: .center)
									}
								}
							}
						}
					}
				}
			}
			.navigationTitle(Text(verbatim: timelineModel.nameForDisplay))
			#else
			ScrollViewReader { scrollViewProxy in
				List(timelineItems.items) { timelineItem in
					ZStack {
						let selected = timelineModel.selectedTimelineItemID == timelineItem.article.articleID
						TimelineItemView(selected: selected, width: geometryReaderProxy.size.width, timelineItem: timelineItem)
							.background(TimelineItemFramePreferenceView(timelineItem: timelineItem))
						NavigationLink(destination: ArticleContainerView(),
									   tag: timelineItem.article.articleID,
									   selection: $timelineModel.selectedTimelineItemID) {
							EmptyView()
						}.buttonStyle(PlainButtonStyle())
					}
				}
				.id(timelineModel.listID)
				.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
					for pref in preferences {
						timelineItemFrames[pref.articleID] = pref.frame
					}
				}
				.onChange(of: timelineModel.selectedTimelineItemID) { selectedArticleID in
					let proxyFrame = geometryReaderProxy.frame(in: .global)
					if let articleID = selectedArticleID, let itemFrame = timelineItemFrames[articleID] {
						if itemFrame.minY < proxyFrame.minY + 3 || itemFrame.maxY > proxyFrame.maxY - 3 {
							withAnimation {
								scrollViewProxy.scrollTo(articleID, anchor: .center)
							}
						}
					}
				}
			}
			.navigationBarTitle(Text(verbatim: timelineModel.nameForDisplay), displayMode: .inline)
			#endif
		}
    }

}

struct TimelineItemFramePreferenceKey: PreferenceKey {
	typealias Value = [TimelineItemFramePreference]

	static var defaultValue: [TimelineItemFramePreference] = []
	
	static func reduce(value: inout [TimelineItemFramePreference], nextValue: () -> [TimelineItemFramePreference]) {
		value.append(contentsOf: nextValue())
	}
}

struct TimelineItemFramePreference: Equatable {
	let articleID: String
	let frame: CGRect
}

struct TimelineItemFramePreferenceView: View {
	let timelineItem: TimelineItem
	
	var body: some View {
		GeometryReader { proxy in
			Rectangle()
				.fill(Color.clear)
				.preference(key: TimelineItemFramePreferenceKey.self,
							value: [TimelineItemFramePreference(articleID: timelineItem.article.articleID, frame: proxy.frame(in: .global))])
		}
	}
}