import Foundation
import SwiftUI

/// Type of a widget
typealias WidgetKind = String

protocol WidgetData: Hashable, Decodable {}

/// Represents an home widget in a list.
protocol Widget {
    /// Must be a `SwiftUI.View`
    associatedtype ViewBody: View

    /// Payload required to initialize the widget
    associatedtype Data: WidgetData

    var data: Data { get }
    func make() -> ViewBody

    static var kind: WidgetKind { get }
    init(data: Data)
}

extension Widget {
    static var kind: WidgetKind {
        String(describing: Self.self).replacingOccurrences(of: "Widget", with: "").lowercased()
    }
}

struct AnyWidget: Identifiable {
    private let widget: any Widget
    var id: UUID = .init()
    let kind: WidgetKind
    private let make: () -> AnyView

    init<WidgetType>(_ widget: WidgetType) where WidgetType: Widget {
        self.widget = widget
        self.kind = WidgetType.kind
        self.make = {
            AnyView(widget.make())
        }
    }

    var contentView: AnyView {
        make()
    }
}
