// swift-tools-version: 6.2

import CompilerPluginSupport
import Foundation
import PackageDescription

// MARK: - EnvManager

/* GENERATED BY SPMManifestTool BEGIN */
/* DO NOT EDIT */

public protocol EnvironmentProvider {
    func value(forKey key: String) -> String?
}

import PackageDescription
public struct PackageContextEnvironmentProvider: EnvironmentProvider {
    public init() {}

    public func value(forKey key: String) -> String? {
        Context.environment[key]
    }
}

public final class EnvManager {
    nonisolated(unsafe) public static let shared = EnvManager()

    private var domains: [String] = []
    private var environmentProvider: EnvironmentProvider

    /// When true, append raw key as fallback when searching in domains
    public var includeFallbackToRawKey: Bool = false

    private init() {
        self.environmentProvider = PackageContextEnvironmentProvider()
    }

    /// Set a custom environment provider (useful for testing)
    public func setEnvironmentProvider(_ provider: EnvironmentProvider) {
        self.environmentProvider = provider
    }

    /// Reset domains and environment provider (useful for testing)
    public func reset() {
        domains.removeAll()
        includeFallbackToRawKey = false
        self.environmentProvider = PackageContextEnvironmentProvider()
    }

    public func register(domain: String) {
        domains.append(domain)
    }

    public func withDomain<T>(_ domain: String, perform: () throws -> T) rethrows -> T {
        domains.append(domain)
        defer { domains.removeAll { $0 == domain } }
        return try perform()
    }

    private func envValue<T>(rawKey: String, default defaultValue: T?, searchInDomain: Bool, parser: (String) -> T?) -> T? {
        func parseEnvValue(_ key: String) -> (String, T)? {
            guard let value = environmentProvider.value(forKey: key),
                  let result = parser(value) else { return nil }
            return (value, result)
        }
        var keys: [String] = searchInDomain ? domains.map { "\($0.uppercased())_\(rawKey)" } : []
        if !searchInDomain || includeFallbackToRawKey {
            keys.append(rawKey)
        }
        for key in keys {
            if let (value, result) = parseEnvValue(key) {
                print("[Env] \(key)=\(value) -> \(result)")
                return result
            }
        }
        let primaryKey = keys.first ?? rawKey
        if let defaultValue {
            print("[Env] \(primaryKey) not set -> \(defaultValue)(default)")
        }
        return defaultValue
    }

    public func envBoolValue(rawKey: String, default defaultValue: Bool? = nil, searchInDomain: Bool) -> Bool? {
        envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { value in
            switch value {
            case "1": true
            case "0": false
            default: nil
            }
        }
    }

    public func envIntValue(rawKey: String, default defaultValue: Int? = nil, searchInDomain: Bool) -> Int? {
        envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { Int($0) }
    }

    public func envStringValue(rawKey: String, default defaultValue: String? = nil, searchInDomain: Bool) -> String? {
        envValue(rawKey: rawKey, default: defaultValue, searchInDomain: searchInDomain) { $0 }
    }
}

public func envBoolValue(_ key: String, default defaultValue: Bool = false, searchInDomain: Bool = true) -> Bool {
    EnvManager.shared.envBoolValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)!
}

public func envIntValue(_ key: String, default defaultValue: Int = 0, searchInDomain: Bool = true) -> Int {
    EnvManager.shared.envIntValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)!
}

public func envStringValue(_ key: String, default defaultValue: String, searchInDomain: Bool = true) -> String {
    EnvManager.shared.envStringValue(rawKey: key, default: defaultValue, searchInDomain: searchInDomain)!
}

public func envStringValue(_ key: String, searchInDomain: Bool = true) -> String? {
    EnvManager.shared.envStringValue(rawKey: key, searchInDomain: searchInDomain)
}

/* GENERATED BY SPMManifestTool END */
EnvManager.shared.register(domain: "OpenSwiftUI")

// MARK: - Env and config

#if os(macOS)
// NOTE: #if os(macOS) check is not accurate if we are cross compiling for Linux platform. So we add an env key to specify it.
let buildForDarwinPlatform = envBoolValue("BUILD_FOR_DARWIN_PLATFORM", default: true)
#else
let buildForDarwinPlatform = envBoolValue("BUILD_FOR_DARWIN_PLATFORM")
#endif

let isVDCDocGenerationBuild = envBoolValue("VDC_GENERATE_DOCS", searchInDomain: false)

// Xcode use clang as linker which supports "-iframework" while SwiftPM use swiftc as linker which supports "-Fsystem"
let systemFrameworkSearchFlag = isXcodeEnv ? "-iframework" : "-Fsystem"
let isXcodeEnv = envStringValue("__CFBundleIdentifier", searchInDomain: false) == "com.apple.dt.Xcode"
let development = envBoolValue("DEVELOPMENT", default: false)
let warningsAsErrorsCondition = envBoolValue("WERROR", default: isXcodeEnv && development)

let swiftCorelibsPath = envStringValue("LIB_SWIFT_PATH") ?? "\(Context.packageDirectory)/Sources/SwiftCorelibs/include"

let releaseVersion = envIntValue("TARGET_RELEASE", default: 2024)

let libraryEvolutionCondition = envBoolValue("LIBRARY_EVOLUTION", default: buildForDarwinPlatform)
let compatibilityTestCondition = envBoolValue("COMPATIBILITY_TEST")

let useLocalDeps = envBoolValue("USE_LOCAL_DEPS", default: false)
let versionedDocCPlugin = envBoolValue("VERSIONED_DOCC_PLUGIN", default: false)

// For OpenAttributeGraphShims
let computeCondition = envBoolValue("OPENATTRIBUTESHIMS_COMPUTE", default: false)
let danceUIGraphCondition = envBoolValue("OPENATTRIBUTESHIMS_DANCEUIGRAPH", default: false)
let attributeGraphCondition = envBoolValue("OPENATTRIBUTESHIMS_ATTRIBUTEGRAPH", default: false)

let renderBoxCondition = envBoolValue("RENDERBOX", default: buildForDarwinPlatform)

let linkCoreUI = envBoolValue("LINK_COREUI", default: buildForDarwinPlatform)
let linkCoreSVG = envBoolValue("LINK_CORESVG", default: buildForDarwinPlatform)
let linkSFSymbols = envBoolValue("LINK_SFSYMBOLS", default: buildForDarwinPlatform)
let linkBacklightServices = envBoolValue("LINK_BACKLIGHTSERVICES", default: buildForDarwinPlatform)
let linkGestures = envBoolValue("LINK_GESTURES", default: buildForDarwinPlatform && releaseVersion >= 2025)
// This should be disabled for UI test target due to link issue of Testing.
// Only enable for non-UI test targets.
let linkTesting = envBoolValue("LINK_TESTING")

let symbolLocatorCondition = envBoolValue("SYMBOL_LOCATOR", default: buildForDarwinPlatform)
let openCombineCondition = envBoolValue("OPENCOMBINE", default: !buildForDarwinPlatform)
let swiftLogCondition = envBoolValue("SWIFT_LOG", default: !buildForDarwinPlatform)
let swiftCryptoCondition = envBoolValue("SWIFT_CRYPTO", default: !buildForDarwinPlatform)
let renderGTKCondition = envBoolValue("RENDER_GTK", default: !buildForDarwinPlatform)

let swiftUIRenderCondition = envBoolValue("SWIFTUI_RENDERER", default: false)

let ignoreAvailability = envBoolValue("IGNORE_AVAILABILITY", default: !isVDCDocGenerationBuild && !compatibilityTestCondition)

// Run @OpenSwiftUIProject/DarwinPrivateFrameworks repo's Scripts/install_internal_sdk.sh XRSimulator to install internal XRSimulator SDK
let internalXRSDK = envBoolValue("INTERNAL_XR_SDK")
let enablePrivateImports = envBoolValue("ENABLE_PRIVATE_IMPORTS", default: true)
let enableRuntimeConcurrencyCheck = envBoolValue("ENABLE_RUNTIME_CONCURRENCY_CHECK")

let bridgeFramework = envStringValue("OPENSWIFTUI_BRIDGE_FRAMEWORK", default: "SwiftUI")

// Workaround iOS CI build issue (We need to disable this on iOS CI)
let supportMultiProducts: Bool = envBoolValue("SUPPORT_MULTI_PRODUCTS", default: true)

/// CGFloat and CGRect def in CFCGTypes.h will conflict with Foundation's CGSize/CGRect def on Linux.
/// macOS: true -> no issue
/// macOS: false -> use Swift implementation with OpenCoreGraphics Swift CGPath
/// Linux: true + No CGPathRef support in ORBPath -> confilict with Foundation def
/// Linux: false -> use Swift implementation with OpenCoreGraphics Swift CGPath
let cfCGTypes = envBoolValue("CF_CGTYPES", default: buildForDarwinPlatform)

// MARK: - Shared Settings

var sharedCSettings: [CSetting] = [
    .define("NDEBUG", .when(configuration: .release)),
    // Rewrite malloc() to malloc_type_malloc() for type-isolated allocation buckets (xzone malloc).
    .unsafeFlags(["-ftyped-memory-operations"], .when(platforms: .darwinPlatforms)),
    .unsafeFlags(["-fmodules"]),
    .define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])),
    .unsafeFlags(["-isystem", swiftCorelibsPath], .when(platforms: .nonDarwinPlatforms)),
]

var sharedCxxSettings: [CXXSetting] = [
    .define("NDEBUG", .when(configuration: .release)),
    // Rewrite malloc() to malloc_type_malloc() for type-isolated allocation buckets (xzone malloc).
    .unsafeFlags(["-ftyped-memory-operations"], .when(platforms: .darwinPlatforms)),
    // Rewrite operator new/delete to typed variants (operator new(size_t, std::__type_descriptor_t)).
    .unsafeFlags(["-ftyped-cxx-new-delete"], .when(platforms: .darwinPlatforms)),
    .unsafeFlags(["-fcxx-modules"]),
    .define("_WASI_EMULATED_SIGNAL", .when(platforms: [.wasi])),
    .unsafeFlags(["-isystem", swiftCorelibsPath], .when(platforms: .nonDarwinPlatforms)),
]

var sharedSwiftSettings: [SwiftSetting] = [
    .enableUpcomingFeature("BareSlashRegexLiterals"),
    .enableUpcomingFeature("InternalImportsByDefault"),
    .enableUpcomingFeature("InferSendableFromCaptures"),
    .enableExperimentalFeature("Extern"),
    // FIXME: -unavailable-decl-optimization=stub is not working somehow (eg. Color.vibrancy). Dig into this later
    .unsafeFlags(["-unavailable-decl-optimization=stub"]),
    .swiftLanguageMode(.v5),

    .define("OPENSWIFTUI_RELEASE_\(releaseVersion)"),
    .unsafeFlags(["-Xfrontend", "-experimental-spi-only-imports"]),
]

if releaseVersion >= 2021 {
    for year in 2021 ... releaseVersion {
        sharedSwiftSettings.append(.define("OPENSWIFTUI_SUPPORT_\(year)_API"))
    }
}
if libraryEvolutionCondition {
    // NOTE: -enable-library-evolution will cause module verify failure for `swift build`.
    // Either set OPENSWIFTUI_LIBRARY_EVOLUTION=0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build`
    sharedSwiftSettings.append(.unsafeFlags(["-enable-library-evolution", "-no-verify-emitted-module-interface"]))
}
if !compatibilityTestCondition {
    sharedCSettings.append(.define("OPENSWIFTUI"))
    sharedCxxSettings.append(.define("OPENSWIFTUI"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI"))
}

if development {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_DEVELOPMENT"))
}

sharedCSettings.append(.define("OPENSWIFTUI_LINK_COREUI", to: linkCoreUI ? "1" : "0"))
sharedCxxSettings.append(.define("OPENSWIFTUI_LINK_COREUI", to: linkCoreUI ? "1" : "0"))
if linkCoreUI {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_COREUI"))
}

sharedCSettings.append(.define("OPENSWIFTUI_LINK_CORESVG", to: linkCoreSVG ? "1" : "0"))
sharedCxxSettings.append(.define("OPENSWIFTUI_LINK_CORESVG", to: linkCoreSVG ? "1" : "0"))
if linkCoreSVG {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_CORESVG"))
}

if linkSFSymbols {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_SFSYMBOLS"))
}

sharedCSettings.append(
    .define(
        "OPENSWIFTUI_LINK_BACKLIGHTSERVICES",
        to: linkBacklightServices ? "1" : "0",
        .when(platforms: [.iOS, .visionOS])
    )
)
sharedCxxSettings.append(
    .define(
        "OPENSWIFTUI_LINK_BACKLIGHTSERVICES",
        to: linkBacklightServices ? "1" : "0",
        .when(platforms: [.iOS, .visionOS])
    )
)
if linkBacklightServices {
    sharedSwiftSettings.append(
        .define(
            "OPENSWIFTUI_LINK_BACKLIGHTSERVICES",
            .when(platforms: [.iOS, .visionOS])
        )
    )
}
if linkGestures {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_GESTURES"))
}

if swiftUIRenderCondition {
    sharedCSettings.append(.define("OPENSWIFTUI_SWIFTUI_RENDERER", .when(platforms: .darwinPlatforms)))
    sharedCxxSettings.append(.define("OPENSWIFTUI_SWIFTUI_RENDERER", .when(platforms: .darwinPlatforms)))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_SWIFTUI_RENDERER", .when(platforms: .darwinPlatforms)))
}

if linkTesting {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_LINK_TESTING"))
}

if warningsAsErrorsCondition {
    // Hold off the werror feature as we can't avoid the concurrency warning.
    // Since there is no such group for diagnostic we want to ignore, we enable werror for all known groups instead.
    // See detail on [#443](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0443-warning-control-flags.md)
    // items we want it to be error:
    // [remove_package_import]
    // items we want to ignore:
    // [error_from_clang] [error_in_future_swift_version]
    // sharedSwiftSettings.append(.unsafeFlags(["-warnings-as-errors"]))
    sharedSwiftSettings.append(.unsafeFlags(["-Werror", "Unsafe"]))
    sharedSwiftSettings.append(.unsafeFlags(["-Werror", "UnknownWarningGroup"]))
    sharedSwiftSettings.append(.unsafeFlags(["-Werror", "ExistentialAny"]))

    // This will cause conflict when used by Xcode from a non-local dependency
    // "Conflicting options '-Wwarning' and '-suppress-warnings'"
    // See: https://forums.swift.org/t/warnings-as-errors-in-sub-packages/70810
    // So do not enable it by default here.
    sharedSwiftSettings.append(.unsafeFlags(["-Wwarning", "DeprecatedDeclaration"])) // We want to use deprecated APIs in test targets)
}

if libraryEvolutionCondition && !openCombineCondition && !swiftLogCondition {
    // NOTE: -enable-library-evolution will cause module verify failure for `swift build`.
    // Either set OPENSWIFTUI_LIBRARY_EVOLUTION=0 or add `-Xswiftc -no-verify-emitted-module-interface` after `swift build`
    sharedSwiftSettings.append(.unsafeFlags(["-enable-library-evolution", "-no-verify-emitted-module-interface"]))
}

if !compatibilityTestCondition {
    sharedSwiftSettings.append(.define("OPENSWIFTUI"))
}

sharedSwiftSettings.append(contentsOf: [SwiftSetting].availabilityMacroSettings(ignoreAvailability: ignoreAvailability))

sharedCSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK", to: internalXRSDK ? "1" : "0"))
sharedCxxSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK", to: internalXRSDK ? "1" : "0"))
if internalXRSDK {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_INTERNAL_XR_SDK"))
}

if enablePrivateImports {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_ENABLE_PRIVATE_IMPORTS"))
    sharedSwiftSettings.append(.unsafeFlags(["-Xfrontend", "-enable-private-imports"]))
}

if enableRuntimeConcurrencyCheck {
    sharedSwiftSettings.append(.define("OPENSWIFTUI_ENABLE_RUNTIME_CONCURRENCY_CHECK"))
}

if cfCGTypes {
    sharedCSettings.append(.define("OPENSWIFTUI_CF_CGTYPES"))
    sharedCxxSettings.append(.define("OPENSWIFTUI_CF_CGTYPES"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_CF_CGTYPES"))
    sharedCSettings.append(.define("OPENRENDERBOX_CF_CGTYPES"))
    sharedCxxSettings.append(.define("OPENRENDERBOX_CF_CGTYPES"))
    sharedSwiftSettings.append(.define("OPENRENDERBOX_CF_CGTYPES"))
}

if computeCondition {
    sharedCSettings.append(.define("OPENSWIFTUI_COMPUTE"))
    sharedCxxSettings.append(.define("OPENSWIFTUI_COMPUTE"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_COMPUTE"))
} else if danceUIGraphCondition {
    sharedCSettings.append(.define("OPENSWIFTUI_DANCEUIGRAPH"))
    sharedCxxSettings.append(.define("OPENSWIFTUI_DANCEUIGRAPH"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_DANCEUIGRAPH"))
} else if attributeGraphCondition {
    sharedCSettings.append(.define("OPENSWIFTUI_ATTRIBUTEGRAPH"))
    sharedCxxSettings.append(.define("OPENSWIFTUI_ATTRIBUTEGRAPH"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_ATTRIBUTEGRAPH"))
}

if renderBoxCondition {
    sharedCSettings.append(.define("OPENSWIFTUI_RENDERBOX"))
    sharedCxxSettings.append(.define("OPENSWIFTUI_RENDERBOX"))
    sharedSwiftSettings.append(.define("OPENSWIFTUI_RENDERBOX"))
}

// MARK: - Extension

extension Target {
    func addAGSettings() {
        // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message
        // "could not determine executable path for bundle 'AttributeGraph.framework'"
        dependencies.append(.product(name: "AttributeGraph", package: "DarwinPrivateFrameworks"))
    }

    func addRBSettings() {
        // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message
        // "could not determine executable path for bundle 'RenderBox.framework'"
        dependencies.append(.product(name: "RenderBox", package: "DarwinPrivateFrameworks"))
    }

    func addCoreUISettings() {
        // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message
        // "could not determine executable path for bundle 'CoreUI.framework'"
        dependencies.append(.product(name: "CoreUI", package: "DarwinPrivateFrameworks"))
    }

    func addCoreSVGSettings() {
        // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message
        // "could not determine executable path for bundle 'CoreSVG.framework'"
        dependencies.append(.product(name: "CoreSVG", package: "DarwinPrivateFrameworks"))
    }

    func addSFSymbolsSettings() {
        dependencies.append(.product(name: "SFSymbols", package: "DarwinPrivateFrameworks"))
    }

    func addBacklightServicesSettings() {
        // FIXME: Weird SwiftPM behavior for test Target. Otherwize we'll get the following error message
        // "could not determine executable path for bundle 'BacklightServices.framework'"
        dependencies.append(
            .product(
                name: "BacklightServices",
                package: "DarwinPrivateFrameworks",
                condition: .when(platforms: [.iOS, .visionOS])
            )
        )
    }

    func addGesturesSettings() {
        dependencies.append(.product(name: "Gestures", package: "DarwinPrivateFrameworks"))
    }

    func addOpenCombineSettings() {
        dependencies.append(.product(name: "OpenCombine", package: "OpenCombine"))
        dependencies.append(.product(name: "OpenCombineFoundation", package: "OpenCombine"))
        var swiftSettings = swiftSettings ?? []
        swiftSettings.append(.define("OPENSWIFTUI_OPENCOMBINE"))
        self.swiftSettings = swiftSettings
    }

    func addOpenCombineCSettings() {
        var cSettings = cSettings ?? []
        cSettings.append(.define("OPENSWIFTUI_OPENCOMBINE"))
        self.cSettings = cSettings

        var cxxSettings = cxxSettings ?? []
        cxxSettings.append(.define("OPENSWIFTUI_OPENCOMBINE"))
        self.cxxSettings = cxxSettings
    }

    func addSwiftLogSettings() {
        dependencies.append(.product(name: "Logging", package: "swift-log"))
        var swiftSettings = swiftSettings ?? []
        swiftSettings.append(.define("OPENSWIFTUI_SWIFT_LOG"))
        self.swiftSettings = swiftSettings
    }

    func addSwiftCryptoSettings() {
        dependencies.append(.product(name: "Crypto", package: "swift-crypto"))
        var swiftSettings = swiftSettings ?? []
        swiftSettings.append(.define("OPENSWIFTUI_SWIFT_CRYPTO"))
        self.swiftSettings = swiftSettings
    }
}

extension [Platform] {
    static var darwinPlatforms: [Platform] {
        [.macOS, .iOS, .macCatalyst, .tvOS, .watchOS, .visionOS]
    }

    static var nonDarwinPlatforms: [Platform] {
        [.linux, .android, .wasi, .openbsd, .windows]
    }
}

extension [SwiftSetting] {
    fileprivate func compatibilityTestSettings() -> Self {
        self + (compatibilityTestCondition ? [
            .unsafeFlags(["-I\(Context.packageDirectory)/Example/Modules/Platform/cocoa"]),
        ] : [])
    }

    /// Settings which define commonly-used OS availability macros.
    ///
    /// These leverage a pseudo-experimental feature in the Swift compiler for
    /// setting availability definitions, which was added in
    /// [swift#65218](https://github.com/swiftlang/swift/pull/65218).
    fileprivate static func availabilityMacroSettings(ignoreAvailability: Bool) -> Self {
        let minimumVersion = "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, visionOS 1.0"
        return [
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_0:\(ignoreAvailability ? minimumVersion : "iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v1_4:\(ignoreAvailability ? minimumVersion : "iOS 13.4, macOS 10.15.4, tvOS 13.4, watchOS 6.2")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_0:\(ignoreAvailability ? minimumVersion : "iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_macOS_v2_0:\(ignoreAvailability ? minimumVersion : "macOS 11.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_1:\(ignoreAvailability ? minimumVersion : "iOS 14.2, macOS 11.0, tvOS 14.1, watchOS 7.1")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v2_3:\(ignoreAvailability ? minimumVersion : "iOS 14.5, macOS 11.3, tvOS 14.5, watchOS 7.4")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_0:\(ignoreAvailability ? minimumVersion : "iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_2:\(ignoreAvailability ? minimumVersion : "iOS 15.2, macOS 12.1, tvOS 15.2, watchOS 8.3")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v3_4:\(ignoreAvailability ? minimumVersion : "iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_0:\(ignoreAvailability ? minimumVersion : "iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_1:\(ignoreAvailability ? minimumVersion : "iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v4_4:\(ignoreAvailability ? minimumVersion : "iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_0:\(ignoreAvailability ? minimumVersion : "iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_1:\(ignoreAvailability ? minimumVersion : "iOS 17.1, macOS 14.1, tvOS 17.1, watchOS 10.1, visionOS 1.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_2:\(ignoreAvailability ? minimumVersion : "iOS 17.2, macOS 14.2, tvOS 17.2, watchOS 10.2, visionOS 1.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_4:\(ignoreAvailability ? minimumVersion : "iOS 17.4, macOS 14.4, tvOS 17.4, watchOS 10.4, visionOS 1.1")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v5_5:\(ignoreAvailability ? minimumVersion : "iOS 17.5, macOS 14.5, tvOS 17.5, watchOS 10.5, visionOS 1.2")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v6_0:\(ignoreAvailability ? minimumVersion : "iOS 18.0, macOS 15.0, tvOS 18.0, watchOS 11.0, visionOS 2.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v7_0:\(ignoreAvailability ? minimumVersion : "iOS 26.0, macOS 26.0, tvOS 26.0, watchOS 26.0, visionOS 26.0")"),
            .enableExperimentalFeature("AvailabilityMacro=OpenSwiftUI_v8_0:\(ignoreAvailability ? minimumVersion : "iOS 27.0, macOS 27.0, tvOS 27.0, watchOS 27.0, visionOS 27.0")"),
            .enableExperimentalFeature("AvailabilityMacro=_distantFuture:iOS 99.0, macOS 99.0, tvOS 99.0, watchOS 99.0, visionOS 99.0"),
        ]
    }
}

// MARK: - Targets

// MARK: - CGTK Target

let cgtkTarget = Target.systemLibrary(
    name: "CGTK",
    pkgConfig: "gtk4",
    providers: [
        .brew(["gtk4"]),
        .apt(["libgtk-4-dev clang"]),
    ]
)

// MARK: - OpenSwiftUISPI Target

let openSwiftUISPITarget = Target.target(
    name: "OpenSwiftUI_SPI",
    dependencies: [
        .product(name: "OpenRenderBoxShims", package: "OpenRenderBox"),
    ],
    publicHeadersPath: ".",
    cSettings: sharedCSettings + [.define("_GNU_SOURCE", .when(platforms: .nonDarwinPlatforms))],
    cxxSettings: sharedCxxSettings,
    linkerSettings: [
        // -lMobileGestalt
        // For MGCopyAnswer API support
        .linkedLibrary("MobileGestalt", .when(platforms: .darwinPlatforms)),
    ] + (swiftUIRenderCondition ? [
        // For Interpose.c or we can choose to use dlsm approach to load them dynamically
        .linkedFramework("SwiftUI", .when(platforms: .darwinPlatforms))
    ] : [])
)

let openSwiftUISPITestTarget = Target.testTarget(
    name: "OpenSwiftUI_SPITests",
    dependencies: [
        "OpenSwiftUI_SPI",
        // For ProtocolDescriptor symbol linking
        "OpenSwiftUI",
        .product(name: "Numerics", package: "swift-numerics"),
    ],
    exclude: ["README.md"],
    swiftSettings: sharedSwiftSettings
)

// MARK: - OpenSwiftUIMacros Target

let openSwiftUIMacrosTarget = Target.macro(
    name: "OpenSwiftUIMacros",
    dependencies: [
        .product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
        .product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
    ],
    swiftSettings: sharedSwiftSettings
)

let openSwiftUIMacrosTestTarget = Target.testTarget(
    name: "OpenSwiftUIMacrosTests",
    dependencies: [
        "OpenSwiftUIMacros",
        .product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
    ],
    swiftSettings: sharedSwiftSettings
)

// MARK: - OpenSwiftUICore Target

// NOTE:
// In macOS: Mac Catalyst App will use macOS-varient build of SwiftUI.framework in /System/Library/Framework and iOS varient of SwiftUI.framework in /System/iOSSupport/System/Library/Framework
// Add `|| Mac Catalyst` check everywhere in `OpenSwiftUICore` and `OpenSwiftUI_SPI`.
let openSwiftUICoreTarget = Target.target(
    name: "OpenSwiftUICore",
    dependencies: [
        "OpenSwiftUI_SPI",
        "OpenSwiftUIMacros",
        .product(name: "OpenCoreGraphicsShims", package: "OpenCoreGraphics"),
        .product(name: "OpenQuartzCoreShims", package: "OpenCoreGraphics"),
        .product(name: "OpenAttributeGraphShims", package: "OpenAttributeGraph"),
        .product(name: "OpenRenderBoxShims", package: "OpenRenderBox"),
        .product(name: "OpenObservation", package: "OpenObservation"),
    ] + (swiftUIRenderCondition && symbolLocatorCondition ? ["OpenSwiftUISymbolDualTestsSupport"] : []),
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings + [
        .unsafeFlags(["-module-abi-name", "OpenSwiftUI"]),
    ],
    linkerSettings: computeCondition ? [
        .linkedLibrary("c++", .when(platforms: .darwinPlatforms)),
    ] : []
)

let openSwiftUICoreTestTarget = Target.testTarget(
    name: "OpenSwiftUICoreTests",
    dependencies: [
        "OpenSwiftUI", // NOTE: For the Glue link logic only, do not call `import OpenSwiftUI` in this target
        "OpenSwiftUICore",
        "OpenSwiftUITestsSupport",
        .product(name: "Numerics", package: "swift-numerics"),
    ],
    exclude: ["README.md"],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

// MARK: OpenSwiftUI Target

let cOpenSwiftUITarget = Target.target(
    name: "COpenSwiftUI",
    publicHeadersPath: ".",
    cSettings: sharedCSettings + [
        .headerSearchPath("../OpenSwiftUI_SPI"),
    ],
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

let cOpenSwiftUITestTarget = Target.testTarget(
    name: "COpenSwiftUITests",
    dependencies: [
        "OpenSwiftUI",
        .product(name: "Numerics", package: "swift-numerics"),
    ],
    swiftSettings: sharedSwiftSettings
)

let openSwiftUITarget = Target.target(
    name: "OpenSwiftUI",
    dependencies: [
        "OpenSwiftUICore",
        "COpenSwiftUI",
    ],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings,
    linkerSettings: [
        // Force Objective-C categories from static COpenSwiftUI into the final framework.
        .unsafeFlags(["-Xlinker", "-ObjC"], .when(platforms: .darwinPlatforms)),
        // -framework CoreServices
        // For CS private API link support
        .linkedFramework("CoreServices", .when(platforms: [.iOS])),
        // -lAccessibility
        // For Accessibility private API link support
        .linkedLibrary("Accessibility", .when(platforms: [.iOS])),
    ]
)

let openSwiftUITestsSupportTarget = Target.target(
    name: "OpenSwiftUITestsSupport",
    dependencies: (compatibilityTestCondition ? [] : ["OpenSwiftUI"]),
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings.compatibilityTestSettings()
)

let openSwiftUIExtensionTarget = Target.target(
    name: "OpenSwiftUIExtension",
    dependencies: [
        "OpenSwiftUI",
    ],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

let openSwiftUITestTarget = Target.testTarget(
    name: "OpenSwiftUITests",
    dependencies: [
        "OpenSwiftUI",
        "OpenSwiftUITestsSupport",
    ],
    exclude: ["README.md"],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

let openSwiftUICompatibilityTestTarget = Target.testTarget(
    name: "OpenSwiftUICompatibilityTests",
    dependencies: [
        "OpenSwiftUITestsSupport",
        .product(name: "Numerics", package: "swift-numerics"),
    ] + (compatibilityTestCondition ? [] : ["OpenSwiftUI"]),
    exclude: ["README.md"],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings.compatibilityTestSettings()
)

// MARK: - OpenSwiftUIBridge Target

let openSwiftUIBridgeTarget = Target.target(
    name: "OpenSwiftUIBridge",
    dependencies: [
        "OpenSwiftUI",
    ],
    sources: ["Bridgeable.swift", bridgeFramework],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

let openSwiftUIBridgeTestTarget = Target.testTarget(
    name: "OpenSwiftUIBridgeTests",
    dependencies: [
        "OpenSwiftUIBridge",
        "OpenSwiftUITestsSupport",
    ],
    exclude: ["README.md"],
    sources: ["BridgeableTests.swift", bridgeFramework],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

// MARK: - OpenSwiftUISymbolDualTests Target

let openSwiftUISymbolDualTestsSupportTarget = Target.target(
    name: "OpenSwiftUISymbolDualTestsSupport",
    dependencies: [
        .product(name: "SymbolLocator", package: "SymbolLocator"),
    ],
    publicHeadersPath: ".",
    cSettings: sharedCSettings + [
        .headerSearchPath("../OpenSwiftUI_SPI"),
    ],
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

let openSwiftUISymbolDualTestsTarget = Target.testTarget(
    name: "OpenSwiftUISymbolDualTests",
    dependencies: [
        "OpenSwiftUI",
        "OpenSwiftUITestsSupport",
        "OpenSwiftUISymbolDualTestsSupport",
        .product(name: "Numerics", package: "swift-numerics"),
    ],
    exclude: ["README.md"],
    cSettings: sharedCSettings,
    cxxSettings: sharedCxxSettings,
    swiftSettings: sharedSwiftSettings
)

// MARK: - Products

let configuredLibraryType = envStringValue("LIBRARY_TYPE")
let libraryType: PackageDescription.Product.Library.LibraryType?
switch configuredLibraryType {
case "dynamic":
    libraryType = .dynamic
case "static":
    libraryType = .static
default:
    libraryType = nil
}

var products: [PackageDescription.Product] = [
    .library(name: "OpenSwiftUI", type: libraryType, targets: ["OpenSwiftUI"])
]
if supportMultiProducts {
    products += [
        .library(name: "OpenSwiftUICore", type: libraryType, targets: ["OpenSwiftUICore"]),
        .library(name: "OpenSwiftUI_SPI", targets: ["OpenSwiftUI_SPI"]),
        .library(name: "OpenSwiftUIExtension", targets: ["OpenSwiftUIExtension"]),
        .library(name: "OpenSwiftUIBridge", targets: ["OpenSwiftUIBridge"])
    ]
}

// MARK: - Package

let package = Package(
    name: "OpenSwiftUI",
    products: products,
    dependencies: [
        .package(url: "https://github.com/apple/swift-numerics", from: "1.0.3"),
        .package(url: "https://github.com/swiftlang/swift-syntax.git", from: "603.0.0"),
    ],
    targets: [
        openSwiftUISPITarget,
        openSwiftUIMacrosTarget,
        openSwiftUICoreTarget,
        cOpenSwiftUITarget,
        openSwiftUITarget,
        openSwiftUITestsSupportTarget,
        openSwiftUIExtensionTarget,
        openSwiftUIBridgeTarget,
    ]
)

if versionedDocCPlugin {
    package.dependencies.append(
        .package(
            url: "https://github.com/DocCLab/VersionedDocC.git",
            exact: "0.0.14"
        )
    )
}

if renderGTKCondition {
    package.targets.append(cgtkTarget)
}

if !compatibilityTestCondition {
    package.targets += [
        cOpenSwiftUITestTarget,
        openSwiftUISPITestTarget,
        openSwiftUIMacrosTestTarget,
        openSwiftUICoreTestTarget,
        openSwiftUITestTarget,
        openSwiftUIBridgeTestTarget,
    ]
}

if buildForDarwinPlatform {
    package.targets.append(openSwiftUICompatibilityTestTarget)
}

if symbolLocatorCondition {
    package.dependencies.append(
        .package(url: "https://github.com/OpenSwiftUIProject/SymbolLocator.git", from: "0.2.0")
    )
    package.targets += [
        openSwiftUISymbolDualTestsSupportTarget
    ]
    if !compatibilityTestCondition {
        package.targets.append(openSwiftUISymbolDualTestsTarget)
    }
}

if attributeGraphCondition {
    openSwiftUICoreTarget.addAGSettings()

    openSwiftUISPITestTarget.addAGSettings()
    openSwiftUICoreTestTarget.addAGSettings()
    openSwiftUITestTarget.addAGSettings()
    openSwiftUICompatibilityTestTarget.addAGSettings()
    openSwiftUIBridgeTestTarget.addAGSettings()
}

if renderBoxCondition {
    openSwiftUICoreTarget.addRBSettings()
    openSwiftUITarget.addRBSettings()

    openSwiftUISPITestTarget.addRBSettings()
    openSwiftUICoreTestTarget.addRBSettings()
    openSwiftUITestTarget.addRBSettings()
    openSwiftUICompatibilityTestTarget.addRBSettings()
    openSwiftUIBridgeTestTarget.addRBSettings()
}

if linkGestures {
    openSwiftUICoreTarget.addGesturesSettings()
    openSwiftUITarget.addGesturesSettings()

    openSwiftUISPITestTarget.addGesturesSettings()
    openSwiftUICoreTestTarget.addGesturesSettings()
    openSwiftUITestTarget.addGesturesSettings()
    openSwiftUICompatibilityTestTarget.addGesturesSettings()
    openSwiftUIBridgeTestTarget.addGesturesSettings()
}

if attributeGraphCondition || renderBoxCondition || linkGestures {
    let release = EnvManager.shared.withDomain("DarwinPrivateFrameworks") {
        envIntValue("TARGET_RELEASE", default: 2024)
    }
    package.platforms = switch release {
        case 2024: [.iOS(.v18), .macOS(.v15), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v10), .visionOS(.v2)]
        case 2025: [.iOS("26.0"), .macOS("26.0"), .macCatalyst("26.0"), .tvOS("26.0"), .watchOS("26.0"), .visionOS("26.0")]
        default: nil
    }
} else {
    // Keep deployment targets available when optional Darwin integrations are disabled.
    package.platforms = [.iOS(.v18), .macOS(.v15), .macCatalyst(.v18), .tvOS(.v18), .watchOS(.v10), .visionOS(.v2)]
}

if linkCoreUI {
    openSwiftUICoreTarget.addCoreUISettings()
    openSwiftUISPITarget.addCoreUISettings()
}

if linkCoreSVG {
    openSwiftUICoreTarget.addCoreSVGSettings()
    openSwiftUISPITarget.addCoreSVGSettings()
}

if linkSFSymbols {
    openSwiftUICoreTarget.addSFSymbolsSettings()
}

if linkBacklightServices {
    openSwiftUITarget.addBacklightServicesSettings()
    openSwiftUISPITarget.addBacklightServicesSettings()
}

if useLocalDeps {
    var dependencies: [Package.Dependency] = [
        .package(path: "../OpenCoreGraphics"),
        .package(path: "../OpenAttributeGraph"),
        .package(path: "../OpenRenderBox"),
        .package(path: "../OpenObservation"),
    ]
    if attributeGraphCondition || renderBoxCondition || linkCoreUI || linkCoreSVG || linkSFSymbols || linkBacklightServices || linkGestures {
        dependencies.append(.package(path: "../DarwinPrivateFrameworks"))
    }
    package.dependencies += dependencies
} else {
    var dependencies: [Package.Dependency] = [
        .package(url: "https://github.com/OpenSwiftUIProject/OpenCoreGraphics", branch: "main"),
        // FIXME: on Linux platform: OG contains unsafe build flags which prevents us using version dependency
        .package(url: "https://github.com/OpenSwiftUIProject/OpenAttributeGraph", branch: "main"),
        .package(url: "https://github.com/OpenSwiftUIProject/OpenRenderBox", branch: "main"),
        .package(url: "https://github.com/OpenSwiftUIProject/OpenObservation", branch: "main"),
    ]
    if attributeGraphCondition || renderBoxCondition || linkCoreUI || linkCoreSVG || linkSFSymbols || linkGestures {
        dependencies.append(.package(url: "https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git", branch: "main"))
    }
    package.dependencies += dependencies
}

if openCombineCondition {
    package.dependencies.append(
        .package(url: "https://github.com/OpenSwiftUIProject/OpenCombine.git", from: "0.15.0")
    )
    cOpenSwiftUITarget.addOpenCombineCSettings()
    openSwiftUICoreTarget.addOpenCombineSettings()
    openSwiftUITarget.addOpenCombineSettings()
}

if swiftLogCondition {
    package.dependencies.append(
        .package(url: "https://github.com/apple/swift-log", from: "1.5.3")
    )
    openSwiftUICoreTarget.addSwiftLogSettings()
    openSwiftUITarget.addSwiftLogSettings()
    openSwiftUICoreTestTarget.addSwiftLogSettings()
    openSwiftUISymbolDualTestsTarget.addSwiftLogSettings()
}

if swiftCryptoCondition {
    package.dependencies.append(
        .package(url: "https://github.com/apple/swift-crypto.git", from: "3.8.0")
    )
    openSwiftUICoreTarget.addSwiftCryptoSettings()
    openSwiftUITarget.addSwiftCryptoSettings()
}

#if TUIST
import struct ProjectDescription.PackageSettings
import enum ProjectDescription.Product
import enum ProjectDescription.SettingValue
import typealias ProjectDescription.SettingsDictionary

let openSwiftUIBuildAGBackend: String
if let configuredAGBackend = envStringValue("AG_BACKEND_NAME") {
    openSwiftUIBuildAGBackend = configuredAGBackend
} else if computeCondition {
    openSwiftUIBuildAGBackend = "Compute"
} else if danceUIGraphCondition {
    openSwiftUIBuildAGBackend = "DanceUIGraph"
} else if attributeGraphCondition {
    openSwiftUIBuildAGBackend = "AttributeGraph"
} else {
    openSwiftUIBuildAGBackend = "OpenAttributeGraph"
}
let openSwiftUIBuildRendererBackend = envStringValue("RENDERER_BACKEND_NAME") ?? (swiftUIRenderCondition ? "SwiftUI" : "OpenSwiftUI")
let openSwiftUIBuildLibraryType = configuredLibraryType ?? "automatic"
let openSwiftUITargetSettings: SettingsDictionary = [
    "INFOPLIST_FILE": .string("Configurations/OpenSwiftUI-Info.plist"),
    "OPENSWIFTUI_BUILD_AG_BACKEND": .string(openSwiftUIBuildAGBackend),
    "OPENSWIFTUI_BUILD_RENDERER_BACKEND": .string(openSwiftUIBuildRendererBackend),
    "OPENSWIFTUI_BUILD_LIBRARY_TYPE": .string(openSwiftUIBuildLibraryType),
    "OPENSWIFTUI_BUILD_USES_LOCAL_DEPENDENCIES": .string(useLocalDeps ? "YES" : "NO"),
]
let openSwiftUICoreTargetSettings: SettingsDictionary = [
    "DYLIB_INSTALL_NAME_BASE": "@rpath",
    "OTHER_LDFLAGS": "$(inherited) -ObjC",
]

let packageSettings = PackageSettings(
    productTypes: [
        "OpenSwiftUI": ProjectDescription.Product.framework,
        "OpenSwiftUICore": ProjectDescription.Product.framework,
        "OpenSwiftUI_SPI": ProjectDescription.Product.staticFramework,
        "COpenSwiftUI": ProjectDescription.Product.staticFramework,
        "OpenSwiftUIMacros": ProjectDescription.Product.macro,
        "OpenSwiftUITestsSupport": ProjectDescription.Product.staticFramework,
        "OpenSwiftUISymbolDualTestsSupport": ProjectDescription.Product.staticFramework,
        "OpenAttributeGraphShims": ProjectDescription.Product.staticFramework,
        "OpenCoreGraphicsShims": ProjectDescription.Product.framework,
        "OpenObservation": ProjectDescription.Product.framework,
        "OpenObservationCxx": ProjectDescription.Product.staticFramework,
        "OpenQuartzCoreShims": ProjectDescription.Product.framework,
        "OpenRenderBoxShims": ProjectDescription.Product.framework,
        "SymbolLocator": ProjectDescription.Product.staticFramework,
    ],
    baseProductType: ProjectDescription.Product.staticFramework,
    targetSettings: [
        "OpenSwiftUI": .settings(base: openSwiftUITargetSettings),
        "OpenSwiftUICore": .settings(base: openSwiftUICoreTargetSettings),
    ]
)
#endif
