import SwiftUI

struct WidgetDocumentation: Hashable {
    struct Variable: Hashable {
        let name: String
        let type: String
        let documentation: [String]
        let defaultValue: String
    }

    let name: String
    let kind: String
    let variables: [Variable]

    static var all = [Self]()
}

struct HelpWidget: Widget {
    struct Data: WidgetData {
        /// optional identifier of the help widget
        /// e.g. specyfing `help` would only show help documentation
        let tag: String?
    }

    struct ContentView: View {
        let documentation: [WidgetDocumentation]

        @State
        var expandedWidgets = Set<String>()

        private func isExpanded(for info: WidgetDocumentation) -> Bool {
            expandedWidgets.contains(info.kind)
        }

        var body: some View {
            ScrollView {
                VStack(alignment: .leading) {
                    ForEach(documentation, id: \.self) { info in
                        DisclosureGroup(isExpanded: .init(get: {
                            isExpanded(for: info)
                        }, set: { expanded in
                            if expanded {
                                expandedWidgets.insert(info.kind)
                            } else {
                                expandedWidgets.remove(info.kind)
                            }
                        }), content: {
                                VStack(alignment: .leading) {
                                    HStack {
                                        Text("kind")
                                            .bold()
                                        Text(info.kind)
                                            .italic()
                                    }
                                    .font(.headline)

                                    Text("Properties")
                                        .font(.headline)
                                        .bold()
                                    ForEach(info.variables, id: \.self) { field in
                                        if !field.documentation.isEmpty {
                                            ForEach(field.documentation, id: \.self) { doc in
                                                Text("/// " + doc)
                                                    .font(.callout)
                                                    .foregroundColor(.primary.opacity(0.6))
                                            }
                                        }
                                        if field.defaultValue.isEmpty {
                                            Text("\(field.name): \(field.type)")
                                                .font(.callout)
                                        } else {
                                            Text("\(field.name): \(field.type) = \(field.defaultValue)")
                                                .font(.callout)
                                        }
                                    }
                                    .padding(.leading, 10)
                                }
                                .font(.subheadline)
                                .frame(maxWidth: .infinity, alignment: .leading)
                        }, label: {
                            Text(info.name)
                                .font(.title)
                                .fontWeight(.bold)
                        })
                    }
                }
                .animation(.easeInOut(duration: 0.2), value: documentation.count)
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .padding(10)
            .overlay(
                RoundedRectangle(cornerRadius: 12, style: .continuous)
                    .stroke(Color.blue, lineWidth: 2)
            )
        }
    }

    func make() -> some View {
        ContentView(documentation: WidgetDocumentation.all.filter { data.tag == nil || $0.kind == data.tag })
    }

    var data: Data
}
