import SwiftUI

struct SegmentedControlView<Content> : View where Content: View {
    @Binding var selection: Int
    private let itemCount: Int
    private var contentForIndex: ((Int) -> Content)?
    @State private var selectedFrame: CGRect = .zero
    
    private let coordinateSpaceName = "PickerCoordinateSpace"
    
    init(selection: Binding<Int>, itemCount: Int, @ViewBuilder contentForIndex: @escaping (Int) -> Content) {
        self._selection = selection
        self.contentForIndex = contentForIndex
        self.itemCount = itemCount
        self.textLabels = []
    }
    
    private var textLabels: [String]
    
    var body: some View {
        HStack(spacing: 0) {
            ForEach(0..<itemCount, id: \.self) { contentIndex in
                VStack {
                    Spacer()
                    if let viewBuilder = contentForIndex {
                        viewBuilder(contentIndex)
                    } else {
                        textLabelForIndex(contentIndex)
                    }
                    Spacer()
                }
                .frame(height: 24)
                .tag(contentIndex)
                .onTapGesture {
                    withAnimation {
                        selection = contentIndex
                    }
                }
                .padding(.vertical, 4)
                .padding(.horizontal, 4)
                .background(
                    GeometryReader { geoProxy in
                        Color.clear
                            .onAppear {
                                DispatchQueue.main.async {
                                    updateFrameForIndex(contentIndex, frame: geoProxy.frame(in: .named(coordinateSpaceName)), animated: false)
                                }
                            }
                            .onChange(of: selection) { _ in
                                updateFrameForIndex(contentIndex, frame: geoProxy.frame(in: .named(coordinateSpaceName)))
                            }
                    }
                )
            }
        }
        .coordinateSpace(name: coordinateSpaceName)
        .background(
            ZStack {
                RoundedRectangle(cornerRadius: 7)
                    .stroke(ColorName.background.color(variation: .secondary), lineWidth: 4)
                
                RoundedRectangle(cornerRadius: 7)
                    .fill(ColorName.background.color(variation: .secondary))
                
                    
                
                RoundedRectangle(cornerRadius: 7)
                    .fill(ColorName.background.color(variation: .primary))
                    .frame(width: selectedFrame.width, height: selectedFrame.height)
                    .position(x: selectedFrame.midX, y: selectedFrame.midY)
                
            }
        )
    }
    
    private func updateFrameForIndex(_ index: Int, frame: CGRect, animated: Bool = true) {
        if selection == index {
            if animated {
                withAnimation {
                    selectedFrame = frame
                }
            } else {
                selectedFrame = frame
            }
        }
    }
    
    @ViewBuilder func textLabelForIndex(_ index: Int) -> some View {
        HStack(alignment: .center, spacing: 0) {
            Spacer()
            Text(textLabels[index])
                .textStyle(.segmentedControl, color: ColorName.text.color)
            Spacer()
        }
    }
}

extension SegmentedControlView where Content == Text {
    init(selection: Binding<Int>, items: [String] ) {
        self._selection = selection
        self.itemCount = items.count
        self.textLabels = items
    }
}


private struct PreviewView: View {
    @State var selection: Int = 0
    
    var body: some View {
        NavigationView {
            ZStack {
                Text("\(selection) preview")
                    .opacity(selection == 0 ? 1 : 0)
                
                Label("\(selection) preview", systemImage: ImageName.System.clock.rawValue)
                    .opacity(selection == 1 ? 1 : 0)
                
                Label("\(selection) preview", systemImage: ImageName.System.calendar.rawValue)
                    .opacity(selection == 2 ? 1 : 0)
            }
            .toolbar {
                ToolbarItem(placement: .principal) {
                    SegmentedControlView(selection: $selection,
                                         itemCount: 3) { index in
                        Group {
                            switch index {
                            case 0:
                                HStack(alignment: .center) {
                                    Text("Hello World!")
                                        .textStyle(.subheadline, color: ColorName.text.color)
                                    
                                    Text("13")
                                        .textStyle(.count, color: ColorName.textOnTint.color)
                                        .padding(.horizontal, 6)
                                        .padding(.vertical, 2)
                                        .background(Capsule().fill(ColorName.tint.color))
                                }
                            case 1:
                                ImageName.System.clock.image
                                    .textStyle(.subheadline, color: ColorName.text.color)
                            case 2:
                                Label("Hello World!", systemImage: ImageName.System.calendar.rawValue)
                            default:
                                Text("Hello World!")
                            }
                        }
                        
                    }
                    .frame(width: 300)
                }
            }
        }
        
    }
}

struct Previews_SegmentedControlView_Previews: PreviewProvider {
    static var previews: some View {
        PreviewView()
    }
}
