/**回调通常用在异步返回结果或不同组件之间传递消息
 * 1）模拟Java标准回调逻辑 caller<--->callee
 * 2)
 */
import kotlin.concurrent.thread
interface ICallback {
    //需要回调的方法
    fun callbackMethod(msg: String)
}
//调用者：1）实现接口中回调方法    2）构造被调用者的对象     3）用实现接口的对象（this）调用被调用者的某一特定方法（该方法调用了回调方法）
class Caller:ICallback{
    val callee=Callee()
    fun mySyncFun(){
        println("Caller sync is running....")
        callee.doSomthing(this)
        println("Caller sync finished!")
    }

    fun myAsyncFun(){
        println("Caller async is running....")
        thread{
            callee.doSomthing(this)
        }
        println("Caller async finished!")
    }

    override  fun callbackMethod(msg: String){
        println(msg)
    }

}

//被调用者：1）在定义一个方法，参数为实现接口的对象     2）在该方法中合适的地方调用回调方法
class Callee{
    fun doSomthing(iCallbackObject: ICallback?){
        println("Callee is running....")
        Thread.sleep(2000)
        iCallbackObject?.callbackMethod("Callee Message")
        println("Callee finished")
    }
}

class ICallbackImpl(private val f: (String) -> Unit):ICallback {
    override fun callbackMethod(msg: String) {
        f.invoke(msg)
    }
}

class FooBar {
    lateinit var callbackObject: ICallback
    fun setCallback(callback: ICallback) {
        this.callbackObject = callback
    }

    fun doSth() {
        println("FooBar is running....")
        callbackObject.callbackMethod("FooBar Message")
        println("FooBar finished")
    }
}



fun main(){
    //标准回调概念
    Caller().mySyncFun()
    Caller().myAsyncFun()

    //回调方法常用方式:接口用匿名内部类（对象表达式）来实现
    val fooBar = FooBar()
    fooBar.setCallback(object:ICallback {
        override fun callbackMethod(msg:String) {
            println("对象表达式（直接覆写接口方法）:$msg")
        }
    })
    fooBar.doSth()

    //接口用通用类实现且在主构造器中传递接口方法的具体实现
    fooBar.setCallback(ICallbackImpl{println("实体类（主构造器中传递函数，在覆写的接口方法中直接调用）：$it")})
    fooBar.doSth()

    //单方法Listener调用
    val objB=singleB()
    objB.setListener{msg->println(msg)}
    objB.doSth()

    //多方法Listener调用
    val multiB=MultiB()
    multiB.setSimpleListener {
        onSuccessFun { println(it) }
        onFailedFun { errorCode, msg ->println("$errorCode    $msg") }
    }
    multiB.doSth()

}

//单一方法Listener设置，无需Interface
class singleB{
    lateinit var mListener: (String) -> Unit

    fun setListener(listener: (String) -> Unit) {
        this.mListener = listener
    }
    fun doSth() {
        println("singleB is running....")
        mListener("This is single method listener")
        println("singleB finished")
    }
}

//多方法Listener演示
interface MultiMethodInterface {
    fun onSuccess(response: String)
    fun onFailed(errorCode: Int, msg: String)
}
//调用类，覆写接口方法，直接在其中调用函数变量所代表的方法
class MultiA:MultiMethodInterface{
        // 函数变量，用于在接口方法中调用
        private lateinit var onSuccessVal: (response: String) -> Unit

        // 将外部函数（Lambda表达式）赋值给函数变量
        fun onSuccessFun(listener: (response: String) -> Unit) {
            this.onSuccessVal = listener
        }

        // 接口中回调方法实现，直接调用从外部获取的函数（Lambda表达式）
        override fun onSuccess(response: String) {
            onSuccessVal.invoke(response)
        }

        //  函数变量，用于在接口方法中调用
        private lateinit var onFailedVal: (errorCode: Int, msg: String) -> Unit

        // 将外部函数（Lambda表达式）赋值给函数变量
        fun onFailedFun(listener: (errorCode: Int, msg: String) -> Unit) {
            this.onFailedVal = listener
        }

        // 接口中回调方法实现，直接调用从外部获取的函数（Lambda表达式）
        override fun onFailed(errorCode: Int, msg: String) {
            onFailedVal.invoke(errorCode, msg)
        }
    }

//被调用类，设置Listener为调用类，接收外部传入的函数参数，并用其回调接口方法
class MultiB{
    private lateinit var listener: MultiMethodInterface

    fun setSimpleListener(init: MultiA.() -> Unit) {
        val builder = MultiA()
        builder.init()            //将init中方法设置给其中的函数变量
        this.listener = builder
    }

    fun doSth() {
        println("multiB is running....")
        listener.onSuccess("Success in multi method listener")
        listener.onFailed(101,"eroor in multi method listener")
        println("multiB finished")
    }
}
