// generated by bun run generate from the SwiftUI SDK and codegen/catalog.ts.
// edit the generator or catalog, then regenerate.
import SwiftUI
import UIKit

private final class MeshGradientModel: ObservableObject {
  @Published var meshWidth: Double = 2
  @Published var meshHeight: Double = 2
  @Published var points: String = "[{\"x\":0,\"y\":0},{\"x\":1,\"y\":0},{\"x\":0,\"y\":1},{\"x\":1,\"y\":1}]"
  @Published var colors: [String] = ["#000000","#000000","#000000","#000000"]
  @Published var background: String = "#00000000"
  @Published var smoothsColors: Bool = true
  @Published var colorSpace: String = "device"
  @Published var accessibility = OneNativeAccessibility()
  @Published var swiftStyle = OneNativeStyle()
  var active = false
  var onSDKEvent: ((String, String) -> Void)?
  func emitSDKEvent(_ name: String, _ value: String) { if active { onSDKEvent?(name, value) } }

}
@objcMembers public final class OneNativeMeshGradientView: UIView, OneNativeComposable {
  public var onSDKEvent: ((String, String) -> Void)?

  private var model = MeshGradientModel()
  private var controller: OneNativeHostingController<OneNativeStandalone<MeshGradientContent>>?
  public override init(frame: CGRect) { super.init(frame: frame) }
  required init?(coder: NSCoder) { fatalError("init(coder:) is unavailable") }
  public func configureAccessibility(_ label: String, hint: String, value: String, identifier: String) {
    let next = OneNativeAccessibility(label: label, hint: hint, value: value, identifier: identifier)
    if model.accessibility != next { model.accessibility = next }
  }
  public func configureStyle(_ style: [String: Any]) {
    let next = OneNativeStyle(dictionary: style)
    if model.swiftStyle != next {
      let previousRows = model.swiftStyle.sdkModifiers.filter { $0.first?.hasPrefix("listRow") == true }
      let nextRows = next.sdkModifiers.filter { $0.first?.hasPrefix("listRow") == true }
      model.swiftStyle = next
      if previousRows != nextRows { compositionParent?.refreshRow(for: self) }
    }
  }
  public func configure(_ meshWidth: Double, meshHeight: Double, points: String, background: String, smoothsColors: Bool, colorSpace: String) {
    if model.meshWidth != meshWidth { model.meshWidth = meshWidth }
    if model.meshHeight != meshHeight { model.meshHeight = meshHeight }
    if model.points != points { model.points = points }
    if model.background != background { model.background = background }
    if model.smoothsColors != smoothsColors { model.smoothsColors = smoothsColors }
    if model.colorSpace != colorSpace { model.colorSpace = colorSpace }
  }
  public func setColors(_ items: [String]) {
    guard items.allSatisfy({ oneNativeMeshGradientColor($0) != nil }) else {
      NSLog("OneNative MeshGradient received invalid colors")
      return
    }
    if model.colors != items { model.colors = items }
  }

  private weak var compositionParent: OneNativeCompositionParent?
  public func compositionContent() -> AnyView { AnyView(MeshGradientContent(model: model)) }
  // composed, activation follows the parent: a subtree mounted before root attachment
  // stays silent until the root attaches.
  public func composeInto(_ parent: OneNativeCompositionParent) {
    controller?.detach(); controller = nil
    compositionParent = parent
    bindCallbacks()
    model.active = parent.compositionActive
  }
  public func decompose() { compositionParent = nil; model.active = false }
  public func propagateActive(_ active: Bool) { model.active = active }
  public override func didMoveToWindow() { super.didMoveToWindow(); updateHost() }
  public override func layoutSubviews() { super.layoutSubviews(); updateHost() }
  private func bindCallbacks() {
    model.onSDKEvent = { [weak self] name, value in self?.onSDKEvent?(name, value) }

  }
  private func updateHost() {
    guard compositionParent == nil else { return }
    model.active = false
    guard window != nil else { controller?.detach(); return }
    if controller == nil {
      bindCallbacks()
      controller = OneNativeHostingController(rootView: OneNativeStandalone(content: MeshGradientContent(model: model)))
    }
    controller?.attach(to: self)
    model.active = controller?.isAttached == true
  }
  public func reset() {
    compositionParent = nil
    model.active = false; model.onSDKEvent = nil
    controller?.detach(); controller = nil; model = MeshGradientModel()
  }
}
private struct MeshGradientContent: View {
  @ObservedObject var model: MeshGradientModel
  var body: some View {
    Group {
      if #available(iOS 18.0, *),
        let meshWidth = Int(exactly: model.meshWidth), meshWidth >= 2,
        let meshHeight = Int(exactly: model.meshHeight), meshHeight >= 2,
        let points = oneNativeMeshGradientPoints(model.points),
        points.count == model.colors.count,
        meshWidth <= points.count,
        points.count % meshWidth == 0,
        points.count / meshWidth == meshHeight,
        let background = oneNativeMeshGradientColor(model.background) {
        MeshGradient(
          width: meshWidth,
          height: meshHeight,
          points: points,
          colors: model.colors.compactMap(oneNativeMeshGradientColor),
          background: background,
          smoothsColors: model.smoothsColors,
          colorSpace: model.colorSpace == "perceptual" ? .perceptual : .device
        )
      } else {
        Color.clear
      }
    }
      .oneNativeAccessibility(model.accessibility, decorativeWhenUnlabeled: true)
      .oneNativeStyle(model.swiftStyle, emit: model.emitSDKEvent)
  }
}
private struct OneNativeMeshGradientPoint: Decodable {
  let x: Float
  let y: Float
}

private func oneNativeMeshGradientPoints(_ raw: String) -> [SIMD2<Float>]? {
  guard let data = raw.data(using: .utf8),
    let points = try? JSONDecoder().decode([OneNativeMeshGradientPoint].self, from: data),
    points.allSatisfy({ $0.x.isFinite && $0.y.isFinite }) else { return nil }
  return points.map { SIMD2<Float>($0.x, $0.y) }
}

private func oneNativeMeshGradientColor(_ value: String) -> Color? {
  guard value.first == "#", value.count == 7 || value.count == 9,
    let hex = UInt64(value.dropFirst(), radix: 16) else { return nil }
  let red, green, blue, alpha: UInt64
  if value.count == 7 {
    red = (hex >> 16) & 0xff
    green = (hex >> 8) & 0xff
    blue = hex & 0xff
    alpha = 0xff
  } else {
    red = (hex >> 24) & 0xff
    green = (hex >> 16) & 0xff
    blue = (hex >> 8) & 0xff
    alpha = hex & 0xff
  }
  return Color(.sRGB, red: Double(red) / 255, green: Double(green) / 255,
    blue: Double(blue) / 255, opacity: Double(alpha) / 255)
}
