package org.jetbrains.kotlin.gradle.dsl

import groovy.lang.Closure
import org.gradle.api.DomainObjectSet
import org.gradle.api.Project
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.mpp.*

// DO NOT EDIT MANUALLY! Generated by org.jetbrains.kotlin.generators.gradle.dsl.MppNativeBinaryDSLCodegenKt

abstract class AbstractKotlinNativeBinaryContainer : DomainObjectSet<NativeBinary> {

    abstract val project: Project
    abstract val target: KotlinNativeTarget

    // User-visible constants.
    val DEBUG = NativeBuildType.DEBUG
    val RELEASE = NativeBuildType.RELEASE

    protected abstract fun <T : NativeBinary> createBinaries(
        namePrefix: String,
        baseName: String,
        outputKind: NativeOutputKind,
        buildTypes: Collection<NativeBuildType>,
        create: (name: String, baseName: String, buildType: NativeBuildType, compilation: KotlinNativeCompilation) -> T,
        configure: T.() -> Unit
    )

    /** Provide an access to binaries using the [] operator in Groovy DSL. */
    fun getAt(name: String): NativeBinary = getByName(name)

    /** Provide an access to binaries using the [] operator in Kotlin DSL. */
    operator fun get(name: String): NativeBinary = getByName(name)

    /** Returns a binary with the given [name]. Throws an exception if there is no such binary. */
    abstract fun getByName(name: String): NativeBinary

    /** Returns a binary with the given [name]. Returns null if there is no such binary. */
    abstract fun findByName(name: String): NativeBinary?

    /** Returns an executable with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    abstract fun getExecutable(namePrefix: String, buildType: NativeBuildType): Executable

    /** Returns an executable with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    fun getExecutable(namePrefix: String, buildType: String): Executable =
        getExecutable(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns an executable with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getExecutable(buildType: NativeBuildType): Executable = getExecutable("", buildType)

    /** Returns an executable with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getExecutable(buildType: String): Executable =  getExecutable("", buildType)

    /** Returns an executable with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    abstract fun findExecutable(namePrefix: String, buildType: NativeBuildType): Executable?

    /** Returns an executable with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    fun findExecutable(namePrefix: String, buildType: String): Executable? =
        findExecutable(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns an executable with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findExecutable(buildType: NativeBuildType): Executable? = findExecutable("", buildType)

    /** Returns an executable with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findExecutable(buildType: String): Executable? = findExecutable("", buildType)

    /** Returns a static library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    abstract fun getStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary

    /** Returns a static library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    fun getStaticLib(namePrefix: String, buildType: String): StaticLibrary =
        getStaticLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns a static library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getStaticLib(buildType: NativeBuildType): StaticLibrary = getStaticLib("", buildType)

    /** Returns a static library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getStaticLib(buildType: String): StaticLibrary =  getStaticLib("", buildType)

    /** Returns a static library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    abstract fun findStaticLib(namePrefix: String, buildType: NativeBuildType): StaticLibrary?

    /** Returns a static library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    fun findStaticLib(namePrefix: String, buildType: String): StaticLibrary? =
        findStaticLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns a static library with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findStaticLib(buildType: NativeBuildType): StaticLibrary? = findStaticLib("", buildType)

    /** Returns a static library with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findStaticLib(buildType: String): StaticLibrary? = findStaticLib("", buildType)

    /** Returns a shared library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    abstract fun getSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary

    /** Returns a shared library with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    fun getSharedLib(namePrefix: String, buildType: String): SharedLibrary =
        getSharedLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns a shared library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getSharedLib(buildType: NativeBuildType): SharedLibrary = getSharedLib("", buildType)

    /** Returns a shared library with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getSharedLib(buildType: String): SharedLibrary =  getSharedLib("", buildType)

    /** Returns a shared library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    abstract fun findSharedLib(namePrefix: String, buildType: NativeBuildType): SharedLibrary?

    /** Returns a shared library with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    fun findSharedLib(namePrefix: String, buildType: String): SharedLibrary? =
        findSharedLib(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns a shared library with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findSharedLib(buildType: NativeBuildType): SharedLibrary? = findSharedLib("", buildType)

    /** Returns a shared library with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findSharedLib(buildType: String): SharedLibrary? = findSharedLib("", buildType)

    /** Returns an Objective-C framework with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    abstract fun getFramework(namePrefix: String, buildType: NativeBuildType): Framework

    /** Returns an Objective-C framework with the given [namePrefix] and the given build type. Throws an exception if there is no such binary.*/
    fun getFramework(namePrefix: String, buildType: String): Framework =
        getFramework(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns an Objective-C framework with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getFramework(buildType: NativeBuildType): Framework = getFramework("", buildType)

    /** Returns an Objective-C framework with the empty name prefix and the given build type. Throws an exception if there is no such binary.*/
    fun getFramework(buildType: String): Framework =  getFramework("", buildType)

    /** Returns an Objective-C framework with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    abstract fun findFramework(namePrefix: String, buildType: NativeBuildType): Framework?

    /** Returns an Objective-C framework with the given [namePrefix] and the given build type. Returns null if there is no such binary. */
    fun findFramework(namePrefix: String, buildType: String): Framework? =
        findFramework(namePrefix, NativeBuildType.valueOf(buildType.toUpperCase()))

    /** Returns an Objective-C framework with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findFramework(buildType: NativeBuildType): Framework? = findFramework("", buildType)

    /** Returns an Objective-C framework with the empty name prefix and the given build type. Returns null if there is no such binary. */
    fun findFramework(buildType: String): Framework? = findFramework("", buildType)

    /** Creates an executable with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun executable(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: Executable.() -> Unit = {}
    ) = createBinaries(namePrefix, namePrefix, NativeOutputKind.EXECUTABLE, buildTypes, ::Executable, configure)

    /** Creates an executable with the empty name prefix for each build type and configures it. */
    @JvmOverloads
    fun executable(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: Executable.() -> Unit = {}
    ) = createBinaries("", project.name, NativeOutputKind.EXECUTABLE, buildTypes, ::Executable, configure)

    /** Creates an executable with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun executable(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = executable(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates an executable with the default name prefix for each build type and configures it. */
    @JvmOverloads
    fun executable(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = executable(buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates a static library with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun staticLib(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: StaticLibrary.() -> Unit = {}
    ) = createBinaries(namePrefix, namePrefix, NativeOutputKind.STATIC, buildTypes, ::StaticLibrary, configure)

    /** Creates a static library with the empty name prefix for each build type and configures it. */
    @JvmOverloads
    fun staticLib(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: StaticLibrary.() -> Unit = {}
    ) = createBinaries("", project.name, NativeOutputKind.STATIC, buildTypes, ::StaticLibrary, configure)

    /** Creates a static library with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun staticLib(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = staticLib(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates a static library with the default name prefix for each build type and configures it. */
    @JvmOverloads
    fun staticLib(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = staticLib(buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates a shared library with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun sharedLib(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: SharedLibrary.() -> Unit = {}
    ) = createBinaries(namePrefix, namePrefix, NativeOutputKind.DYNAMIC, buildTypes, ::SharedLibrary, configure)

    /** Creates a shared library with the empty name prefix for each build type and configures it. */
    @JvmOverloads
    fun sharedLib(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: SharedLibrary.() -> Unit = {}
    ) = createBinaries("", project.name, NativeOutputKind.DYNAMIC, buildTypes, ::SharedLibrary, configure)

    /** Creates a shared library with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun sharedLib(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = sharedLib(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates a shared library with the default name prefix for each build type and configures it. */
    @JvmOverloads
    fun sharedLib(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = sharedLib(buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates an Objective-C framework with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun framework(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: Framework.() -> Unit = {}
    ) = createBinaries(namePrefix, namePrefix, NativeOutputKind.FRAMEWORK, buildTypes, ::Framework, configure)

    /** Creates an Objective-C framework with the empty name prefix for each build type and configures it. */
    @JvmOverloads
    fun framework(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configure: Framework.() -> Unit = {}
    ) = createBinaries("", project.name, NativeOutputKind.FRAMEWORK, buildTypes, ::Framework, configure)

    /** Creates an Objective-C framework with the given [namePrefix] for each build type and configures it. */
    @JvmOverloads
    fun framework(
        namePrefix: String,
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = framework(namePrefix, buildTypes) { ConfigureUtil.configure(configureClosure, this) }

    /** Creates an Objective-C framework with the default name prefix for each build type and configures it. */
    @JvmOverloads
    fun framework(
        buildTypes: Collection<NativeBuildType> = NativeBuildType.DEFAULT_BUILD_TYPES,
        configureClosure: Closure<*>
    ) = framework(buildTypes) { ConfigureUtil.configure(configureClosure, this) }

}