// Generated from "jsfunction/Main.java"
@file:Suppress(
 "ALWAYS_NULL",
 "PARAMETER_NAME_CHANGED_ON_OVERRIDE",
 "SENSELESS_COMPARISON",
 "UNCHECKED_CAST",
 "UNNECESSARY_LATEINIT",
 "UNNECESSARY_NOT_NULL_ASSERTION",
 "UNREACHABLE_CODE",
 "UNUSED_ANONYMOUS_PARAMETER",
 "UNUSED_PARAMETER",
 "UNUSED_VARIABLE",
 "USELESS_CAST",
 "VARIABLE_IN_SINGLETON_WITHOUT_THREAD_LOCAL",
 "VARIABLE_WITH_REDUNDANT_INITIALIZER",
 "REDUNDANT_ELSE_IN_WHEN")

package jsfunction

import javaemul.lang.*
import java.lang.Class
import java.util.ArrayList
import jsinterop.annotations.JsFunction
import jsinterop.annotations.JsMethod
import jsinterop.annotations.JsOptional
import jsinterop.annotations.JsOverlay
import jsinterop.annotations.JsPackage
import jsinterop.annotations.JsProperty
import jsinterop.annotations.JsType
import kotlin.Any
import kotlin.Array
import kotlin.Double
import kotlin.Int
import kotlin.IntArray
import kotlin.Number
import kotlin.String
import kotlin.Suppress
import kotlin.arrayOf
import kotlin.collections.MutableList
import kotlin.jvm.JvmField
import kotlin.jvm.JvmStatic
import kotlin.jvm.javaObjectType

open class Main {
 open fun testJsFunction() {
  val func: JsFunctionImplementation = JsFunctionImplementation()
  func.foo(10)
  Main.callFn(
   Main.createNativeFunction(),
   10,
  )
  val a: Int = func.field
  func.bar()
 }

 open fun testJsFunctionsCapturingLocal() {
  val n: Int = 4
  Main.callFn(
   JsFunctionInterface { number: Int ->
    return@JsFunctionInterface number + n
   },
   n,
  )
  Main.callFn(
   object : JsFunctionInterface {
    override fun foo(a: Int): Int {
     return a + n
    }
   },
   n,
  )
  object : JsFunctionInterface {
   override fun foo(a: Int): Int {
    this@Main.instanceMethod()
    return 0
   }
  }.foo(3)
 }

 open fun testJsFunctionThis() {
  object : JsFunctionInterface {
   override fun foo(a: Int): Int {
    this@Main.instanceMethod()
    return 0
   }
  }.foo(3)
 }

 private fun instanceMethod() {}

 open fun testJsFunctionErasureCasts() {
  val list: MutableList<Function<String?, String?>?> = ArrayList<Function<String, String>>() as MutableList<Function<String?, String?>?>
  Main.acceptsJsFunction(
   list.get(0),
  )
 }

 internal open fun testJsFunctionVarargs_pp_jsfunction(): JsFunctionVarargs? {
  val f: JsFunctionVarargs = JsFunctionVarargs { i: Int, numbers: IntArray? ->
   var sum: Int = i
   for (number in numbers!!) {
    val number_1: Int = number
    sum = sum + number_1
   }
   return@JsFunctionVarargs sum
  }
  return f
 }

 internal open fun testJsFunctionVarargsInnerClass_pp_jsfunction(): JsFunctionVarargs? {
  return object : JsFunctionVarargs {
   override fun m(i: Int, vararg numbers: Int): Int {
    var sum: Int = i
    for (number in numbers!!) {
     val number_1: Int = number
     sum = sum + number_1
    }
    return sum
   }
  }
 }

 open fun testVarArgsMethodReferenceToJsFuncion() {
  val c: ForEachCallBack<ElementalJsFunction?> = ForEachCallBack { arg0: ElementalJsFunction?, arg1: Int, arg2: Array<ElementalJsFunction?>? ->
   return@ForEachCallBack arg0!!.call(arg1, arg2)
  }
 }

 internal open fun <T> acceptsVarargsJsFunctionWithTypeVariable_pp_jsfunction(x: JsFunctionVarargsGenerics<T>?) {}

 internal open fun <T> acceptsVarargsJsFunctionWithParemetrizedType_pp_jsfunction(x: JsFunctionVarargsGenerics<MutableList<T>?>?) {}

 @JsMethod(name = "acceptsVarargsJsFunctionWithTypeVariableInVarargs")
 internal open fun <T> acceptsVarargsJsFunctionWithTypeVariableInVarargs_pp_jsfunction(vararg x: JsFunctionVarargsGenerics<T>?) {
  val x_1: Array<JsFunctionVarargsGenerics<T>?>? = x as Array<JsFunctionVarargsGenerics<T>?>?
 }

 @JsMethod(name = "acceptsVarargsJsFunctionWithParemetrizedTypeInVarargs")
 internal open fun <T> acceptsVarargsJsFunctionWithParemetrizedTypeInVarargs_pp_jsfunction(vararg x: JsFunctionVarargsGenerics<MutableList<T>?>?) {
  val x_1: Array<JsFunctionVarargsGenerics<MutableList<T>?>?>? = x as Array<JsFunctionVarargsGenerics<MutableList<T>?>?>?
 }

 @JsMethod(name = "acceptsJsFunctionInVarargs")
 internal open fun acceptsJsFunctionInVarargs_pp_jsfunction(vararg x: SimpleJsFunction?) {
  val x_1: Array<SimpleJsFunction?>? = x as Array<SimpleJsFunction?>?
 }

 internal open fun testJsFunctionClassLiterals_pp_jsfunction() {
  val array: Array<SimpleJsFunction?> = arrayOf<SimpleJsFunction?>()
  var o: Any = SimpleJsFunction::class.javaObjectType
  o = Array::class.javaObjectType as Class<Array<SimpleJsFunction?>>
 }

 internal open fun testJsFunctionOptional_pp_jsfunction() {
  val f: JsFunctionOptional = JsFunctionOptional { i: Int, n: Double? ->
   return@JsFunctionOptional (i.toDouble() + n!!.toDouble()).toInt()
  }
 }

 @JvmField
 internal var jsFunctionFieldWildcard_pp_jsfunction: ParametricJsFunction<*>? = ParametricJsFunction { event: Any? ->
 }

 @JvmField
 internal var jsFunctionFieldParameterized_pp_jsfunction: ParametricJsFunction<String?>? = ParametricJsFunction { event: String? ->
 }

 internal open fun testFunctionExpressionTypeReplacement_pp_jsfunction() {
  val f: ParametricJsFunction<String?> = ParametricJsFunction { unused: String? ->
   val l: MutableList<MutableList<*>?> = ArrayList<MutableList<*>>() as MutableList<MutableList<*>?>
   l.add(
    ArrayList<String>(),
   )
  }
 }

 internal open fun testJsFunctionPropertyCall_pp_jsfunction() {
  val c: ClassWithJsFunctionProperty = ClassWithJsFunctionProperty()
  c.function_pp_jsfunction!!.call("")
  c.getFunction_pp_jsfunction()!!.call("")
  c.function_pp_jsfunction!!.call("")
  (if (c != null) c.function_pp_jsfunction else null)!!.call("")
 }

 companion object {
  @JvmStatic
  @JsMethod
  fun createNativeFunction(): JsFunctionInterface? {
   return null
  }

  @JvmStatic
  fun callFn(fn: JsFunctionInterface?, a: Int): Int {
   return fn!!.foo(a)
  }

  @JvmStatic
  fun acceptsJsFunction(f: Function<String?, String?>?) {}

  @JvmStatic
  @JsProperty
  private fun setParametricJsFunction(fn: ParametricJsFunction<Any?>?) {}

  @JvmStatic
  @JsProperty
  private fun getParametricJsFunction(): ParametricJsFunction<Any?>? {
   return null
  }

  @JvmStatic
  fun callInterfaceRaw(f: JsBiFunction<Any?, Number?>?, o: Any?, n: Number?): Any? {
   return f!!.apply(o, n)
  }

  @JvmStatic
  fun callInterfaceParameterized(f: JsBiFunction<String?, Int?>?, s: String?): String? {
   return f!!.apply(s, 1)
  }

  @JvmStatic
  fun <U, V: Number?> callInterfaceUnparameterized(f: JsBiFunction<U, V>?, u: U, v: V): U {
   return f!!.apply(u, v)
  }

  @JvmStatic
  fun callImplementorRaw(f: TIntegerJsBiFunction<Any?>?, o: Any?, n: Int?): Any? {
   return f!!.apply(o, n)
  }

  @JvmStatic
  fun callImplementorParameterized(f: TIntegerJsBiFunction<String?>?, s: String?): String? {
   return f!!.apply(s, 1)
  }

  @JvmStatic
  fun testParameterTypes() {
   val tIntegerJsBiFunction: JsBiFunction<Any?, Number?> = TIntegerJsBiFunction<String?>() as JsBiFunction<Any?, Number?>
   val doubleDoubleJsBiFunction: JsBiFunction<Any?, Number?> = DoubleDoubleJsBiFunction() as JsBiFunction<Any?, Number?>
   Main.callInterfaceRaw(tIntegerJsBiFunction, "a", 1)
   Main.callInterfaceRaw(doubleDoubleJsBiFunction, 1.1, 1.1)
   Main.callInterfaceParameterized(
    tIntegerJsBiFunction as JsBiFunction<String?, Int?>?,
    "a",
   )
   Main.callInterfaceUnparameterized<String?, Int?>(
    tIntegerJsBiFunction as JsBiFunction<String?, Int?>?,
    "a",
    1,
   )
   Main.callInterfaceUnparameterized<Double?, Double?>(
    doubleDoubleJsBiFunction as JsBiFunction<Double?, Double?>?,
    1.1,
    1.1,
   )
   Main.callImplementorRaw(
    TIntegerJsBiFunction<Double?>() as TIntegerJsBiFunction<Any?>?,
    1.1,
    1,
   )
   Main.callImplementorParameterized(
    TIntegerJsBiFunction<String?>(),
    "",
   )
   tIntegerJsBiFunction.apply("a", 1)
   doubleDoubleJsBiFunction.apply(1.1, 1.1)
   Main.callOnFunction(
    DoubleDoubleJsBiFunction(),
   )
  }

  @JvmStatic
  @JsMethod
  fun callOnFunction(f: JsBiFunction<Double?, Double?>?): Double {
   return 0.0
  }

  @JvmStatic
  fun testCast() {
   val o: Any = TIntegerJsBiFunction<String?>()
   val rawTIntegerJsBiFunction: TIntegerJsBiFunction<Any?>? = o as TIntegerJsBiFunction<Any?>?
   val parameterizedTIntegerJsBiFunction: TIntegerJsBiFunction<String?>? = o as TIntegerJsBiFunction<String?>?
   val anotherRawJsBiFunction: JsBiFunction<Any?, Number?>? = o as JsBiFunction<Any?, Number?>?
   val anotherParameterizedJsBiFunction: JsBiFunction<String?, Int?>? = o as JsBiFunction<String?, Int?>?
   val doubleDoubleJsBiFunction: DoubleDoubleJsBiFunction? = o as DoubleDoubleJsBiFunction?
  }

  @JvmStatic
  fun testNewInstance() {
   val rawTIntegerJsBiFunction: TIntegerJsBiFunction<Any?> = TIntegerJsBiFunction<Any?>()
   val parameterizedTIntegerJsBiFunction: TIntegerJsBiFunction<String?> = TIntegerJsBiFunction<String?>() as TIntegerJsBiFunction<String?>
   val rawJsBiFunction: JsBiFunction<Any?, Number?> = DoubleDoubleJsBiFunction() as JsBiFunction<Any?, Number?>
  }
 }

 @JsFunction
 fun interface Function<T, U> {
  fun apply(u: U): T
 }

 @JsFunction
 fun interface JsFunctionInterface {
  fun foo(a: Int): Int

  @JsOverlay
  fun overlayMethod(): Int {
   return this@JsFunctionInterface.foo(42)
  }
 }

 class JsFunctionImplementation: JsFunctionInterface {
  @JvmField
  var field: Int = 0

  @JvmField
  var storedThis: JsFunctionImplementation? = null

  @JvmField
  var anotherStoredThis: JsFunctionImplementation? = null

  internal constructor() {
   this.storedThis = this
   this.anotherStoredThis = this as JsFunctionImplementation
  }

  fun bar(): Int {
   return 0
  }

  fun `fun`(): Int {
   this.field = 1
   return this.bar() + this.foo(1)
  }

  override fun foo(a: Int): Int {
   return a + this.bar() + this.field
  }
 }

 open class TestCaptureOuterParametricClass<T> internal constructor() {
  open fun test() {
   val f: Function<Any?, Any?> = Function { `object`: Any? ->
    return@Function ArrayList<T>()
   }
  }
 }

 @JsFunction
 fun interface JsFunctionVarargs {
  fun m(i: Int, vararg numbers: Int): Int
 }

 @JsFunction
 fun interface ForEachCallBack<T> {
  fun onInvoke(p0: T, p1: Int, p2: Array<T>?): Any?
 }

 @JsFunction
 fun interface ElementalJsFunction {
  fun call(vararg args: Any?): Any?
 }

 @JsFunction
 fun interface JsFunctionVarargsGenerics<T> {
  fun m(i: Int, vararg numbers: T): Int
 }

 @JsFunction
 fun interface SimpleJsFunction {
  fun m()
 }

 @JsFunction
 fun interface JsFunctionOptional {
  fun m(i: Int, @JsOptional number: Double?): Int
 }

 class JsFunctionOptionalImpl internal constructor(): JsFunctionOptional {
  override fun m(i: Int, @JsOptional number: Double?): Int {
   return (i.toDouble() + number!!.toDouble()).toInt()
  }
 }

 @JsFunction
 fun interface ParametricJsFunction<E> {
  fun call(event: E)
 }

 interface ApiWithMethodReturningParametricJsFunction {
  fun <T> anApi(): ParametricJsFunction<T>?
 }

 open class Implementor internal constructor(): ApiWithMethodReturningParametricJsFunction {
  @JsMethod
  override fun <T> anApi(): ParametricJsFunction<T>? {
   return null as ParametricJsFunction<T>?
  }
 }

 class ParamtericImplementation<T> internal constructor(): ParametricJsFunction<T> {
  override fun call(t: T) {
   val o: Any? = t as T
  }
 }

 open class ClassWithJsFunctionProperty internal constructor() {
  @JvmField
  internal var function_pp_jsfunction: ParametricJsFunction<String?>? = null

  @JsProperty(name = "function")
  internal open fun getFunction_pp_jsfunction(): ParametricJsFunction<String?>? {
   return null
  }
 }

 @JsFunction
 fun interface JsBiFunction<T, S: Number?> {
  fun apply(t: T, s: S): T
 }

 class DoubleDoubleJsBiFunction: JsBiFunction<Double?, Double?> {
  override fun apply(d: Double?, i: Double?): Double? {
   return d
  }
 }

 class TIntegerJsBiFunction<T>: JsBiFunction<T, Int?> {
  override fun apply(element: T, i: Int?): T {
   return null as T
  }
 }

 @JsType(name = "Array", namespace = JsPackage.GLOBAL, isNative = true)
 open class TestJsFunctionInJsOverlayCapturingOuter internal constructor() {
  @JsOverlay
  internal fun test_pp_jsfunction() {
   this.sort_pp_jsfunction(
    JsFunctionInterface { a: Int ->
     return@JsFunctionInterface if (this@TestJsFunctionInJsOverlayCapturingOuter == null) 0 else 1
    },
   )
  }

  @JsOverlay
  internal fun sort_pp_jsfunction(func: JsFunctionInterface?) {}
 }

 class RecursiveParametricJsFunctionImplementation<T: ParametricJsFunction<T>?> internal constructor(): ParametricJsFunction<T> {
  override fun call(t: T) {}
 }

 class RecursiveJsFunctionImplementation internal constructor(): ParametricJsFunction<RecursiveJsFunctionImplementation?> {
  override fun call(t: RecursiveJsFunctionImplementation?) {}
 }
}
