/**Retrofit自2.6.0版本以后支持Kotlin Coroutine，以使其访问网络更简单
 *1）用Retrofit注解构造网络访问接口
 *2）用上述接口构建retrofit service
 *3）用该service调用网络访问接口中的函数xxx
 *   同步访问：response=service.xxx.excute()
 *   异步访问：service.xxx.enqueue(){
 *               override fun onResponse(){
 *                 }
 *                override fun onFailure(){
 *                }
 *             }
 *   协程访问:GlobalScope.launch {
 *               try {
 *                   val resopnse = withContext(Dispatchers.IO){
 *                           service.xxx
 *                   }catch (e: Exception) {
 *
 *                   }finally {
 *
 *                   }
 *               }
 */
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.*
import java.io.IOException
import java.util.concurrent.TimeUnit

data class Todo(
    val id: Int = 0,
    val title: String = "",
    val completed: Boolean = false
)

//用WanInterface接口构造RetrofitService
class MyRetrofitService {
    private fun getRetrofit(): Retrofit {
        return Retrofit.Builder()
            .baseUrl("https://jsonplaceholder.typicode.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

    fun get():  WebInterface {
        val retrofit = getRetrofit()
        return retrofit.create(WebInterface::class.java)
    }
}

//Retrofit注解与网络接口函数对应
interface WebInterface {
    //普通
    @GET("/todos/{id}")
    fun getTodo1(@Path(value = "id") todoId: Int): Call<Todo>
    
    //协程
    @GET("/todos/{id}")
    suspend fun getTodo2(@Path(value = "id") todoId: Int): Todo

}

/*等效替换：可以将上述二者写在一起
interface WebInterface2 {
    companion object  {
        const val MY_BASE_URL = "https://jsonplaceholder.typicode.com/"
        fun createRetrofitService(): WebInterface2 {
            val okHttpClient = OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).build()
            val retrofitBuilder = Retrofit.Builder()
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(MY_BASE_URL)
                .build()
            return retrofitBuilder.create(WebInterface2::class.java)
        }
    }
    @GET("/todos/{id}")
    suspend fun getTodo2(@Path(value = "id") todoId: Int): Todo
}*/

//同步访问网络
fun getTodos0() {
    val myRetrofitService =  MyRetrofitService().get()
    try {
        val response: Response<Todo> = myRetrofitService.getTodo1(1).execute()
        println("Http sync access succeed!")
        println(response.body())
    } catch (e:IOException ) {
        println("Http sync access failed!")
        println(e)
    }
}

//异步访问网络，普通不用协程
fun getTodos1() {
    val myRetrofitService =  MyRetrofitService().get()
    myRetrofitService.getTodo1(2).enqueue(object : Callback<Todo> {
        override fun onResponse(call: Call<Todo>, response: Response<Todo>) {
            // 成功
            if(response.isSuccessful){
                 println("Http async access succeed!")
                 val todo=response.body()
                 println(todo)
            }
           else  println("Http async access succeed,but response failed!")
        }

        override fun onFailure(call: Call<Todo>, t: Throwable) {
            // 失败
            println("Http async access failed!")
            println(t.message)
        }
    })
}

//协程访问网络
fun getTodos2() {
   val myRetrofitService= MyRetrofitService().get()
   GlobalScope.launch {
        try {
            // 成功
            val todo = withContext(Dispatchers.IO){
                myRetrofitService.getTodo2(3)
                /*等效替换
                WebInterface2.createRetrofitService().getTodo2(4)*/
            }
            println("Http access in coroutine succeed!")
            println(todo)
        }
        catch (e: Exception) {
            // 失败
            println("Http access in coroutine fail! ")
            println(e.message)
        }finally {
            println("Http access in coroutine end! ")
        }
    }
}

fun main() {
    getTodos0()
    getTodos1()
    getTodos2()
}
