//
//  ScorllView_Example.swift
//  RememberbyAnything
//
//  Created by Sean Kim on 5/14/24.
//
import SwiftUI

struct ScorllView_Example: View {
    @StateObject private var scrollViewModel: ScrollViewModel = ScrollViewModel()
    @State var isStartScroll: Bool = true
    
    // scroll 위치 감지 변경하는 부분
    private var scrollObservableView: some View {
        GeometryReader { proxy in
            let offsetY = proxy.frame(in: .global).origin.y
            Color.clear
                .preference(
                    key: ScrollOffsetKey.self,
                    value: offsetY
                    
                )
                .onAppear {
                    scrollViewModel.setOriginOffset(offsetY)
                }
        }
        .frame(height: 0)
    }
    
    var body: some View {
        ScrollViewReader { scroll in
            ScrollView(showsIndicators: false) {
                scrollObservableView.id(-1)
            }
            .onPreferenceChange(ScrollOffsetKey.self) {
                scrollViewModel.setOffset($0)
                self.isStartScroll = scrollViewModel.isStartScroll
            }
            // 스크롤이 시작할 경우 최상단으로 올리는 버튼 그리기
            .overlay(alignment: .top) {
                if isStartScroll {
                    GeometryReader { geo in
                        Button {
                            withAnimation {
                                scroll.scrollTo(-1, anchor: .center)
                            }
                        } label: {
                            Icon.up
                                .font(.nps(size: 30))
                                .foregroundStyle(.brandDeepBlue)
                                .frame(width: geo.size.width, height: isStartScroll ? 30 : 0,alignment: .center)
                                .padding(.init(top: 10, leading: 0, bottom: 20, trailing: 0))
                                .background(
                                    LinearGradient(
                                        colors: [.whiteSora, .whiteSora.opacity(0)],
                                        startPoint: .top,
                                        endPoint: .bottom)
                                )
                        }
                    }
                }
            }
            
        }
    }
}
// MARK: - 스크롤 뷰 관련 modifier
struct HeightPreferenceKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

// 자식뷰에서 상위 뷰로 데이터 전달시 사용 = PreferenceKey
struct ScrollOffsetKey: PreferenceKey {
    static var defaultValue: CGFloat = .zero
    
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value += nextValue()
    }
}

final class ScrollViewModel: ObservableObject {
    @Published var offset: CGFloat = 0
    @Published var isStartScroll: Bool = false
    var originOffset: CGFloat = 0
    var isCheckedOriginOffset: Bool = false
    
    func setOriginOffset(_ offset: CGFloat) {
        guard !isCheckedOriginOffset else { return }
        self.originOffset = offset - 30 // 스크롤 패딩 넣은거 만큼 빼야 함
        self.offset = offset
        isCheckedOriginOffset = true
    }
    
    func setOffset(_ offset: CGFloat) {
        self.offset = offset
        if self.offset < self.originOffset { isStartScroll = true }
        else { isStartScroll = false }
    }
}
