package com.example.demo.controller

import com.example.demo.model.User
import com.example.demo.service.UserService
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.toList
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import org.springframework.context.annotation.Lazy
import org.springframework.messaging.handler.annotation.DestinationVariable
import org.springframework.messaging.handler.annotation.MessageMapping


@RestController
@Lazy
class HomeController(@Autowired @Lazy private val userService: UserService) {
    @GetMapping("/")
    fun index(): Mono<String> {
        return Mono.just("foo")
    }

    @GetMapping("/data")
    fun dataHandler(): Mono<MyData> {
        return Mono.just(MyData(1, "hello2"))
    }

    @GetMapping("/data2")
    suspend fun dataHandler2(): MyData = withContext(Dispatchers.IO) {
        delay(10_000)
        MyData(1, "hello3")
    }

    @GetMapping("/users")
    fun users(): Flux<User> {
        return userService.users()
    }

    @GetMapping("/users2")
    suspend fun users2(): Flow<User> {
        return userService.users2()
    }

    @GetMapping("/users3")
    suspend fun users3() = coroutineScope {
        val fun1 = async {
            userService.users2().toList()
        }

        Pair(fun1.await(), 1)
    }

    @GetMapping("/messages/{userName}")
    suspend fun messages(@PathVariable userName: String) = coroutineScope {
       userService.getUserMessages(userName)
    }

    @MessageMapping("messages.findAll")
    suspend fun all() = coroutineScope {
        userService.getAllMessages()
    }

    @MessageMapping("users.{name}")
    suspend fun getUser(@DestinationVariable name: String) = coroutineScope {
        userService.getUserByName(name)
    }
}

data class MyData(val id: Int, val name2: String)