//
//  OffsetObservableScollView.swift
//  AcaMate
//
//  Created by TAnine on 2/10/25.
//

import SwiftUI
import Combine

struct OffsetObservableScrollView<Content: View>: View {
    var axes: Axis.Set = .vertical
    var showsIndicators: Bool = true

    @Binding var scrollOffset: CGPoint
    @ViewBuilder var content: (ScrollViewProxy) -> Content

    @Namespace var coordinateSpaceName: Namespace.ID

    init(
        _ axes: Axis.Set = .vertical,
        showsIndicators: Bool = true,
        scrollOffset: Binding<CGPoint>,
        @ViewBuilder content: @escaping (ScrollViewProxy) -> Content
    ) {
        self.axes = axes
        self.showsIndicators = showsIndicators
        self._scrollOffset = scrollOffset
        self.content = content
    }

    var body: some View {
        ScrollView(axes, showsIndicators: showsIndicators) {
            ScrollViewReader { scrollViewProxy in
                VStack(spacing: 0) {
                    // 맨 위로 스크롤하기 위한 anchor 뷰 (id "TOP")
                    Color.clear
                        .frame(height: 1)
                        .id("TOP")
                    content(scrollViewProxy)
                        .overlay {
                            GeometryReader { geometryProxy in
                                Color.clear
                                    .preference(
                                        key: ScrollOffsetPreferenceKey.self,
                                        value: CGPoint (
                                            x: -geometryProxy.frame(in: .named(coordinateSpaceName)).minX,
                                            y: -geometryProxy.frame(in: .named(coordinateSpaceName)).minY
                                        )
                                    )
                            }
                        }
                }
            }
        }
        .coordinateSpace(name: coordinateSpaceName)
        .onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
//            printLog("\(scrollOffset) -> \(value)")
            scrollOffset = value
            
        }
    }
}

struct ScrollOffsetPreferenceKey: PreferenceKey {
    static var defaultValue: CGPoint = .zero

    static func reduce(value: inout CGPoint, nextValue: () -> CGPoint) {
        value = nextValue()
    }
}
