package it.unisannio.ding.ids.wedroid.app.data.repository import android.util.Log import it.unisannio.ding.ids.wedroid.app.data.dao.BoardDao import it.unisannio.ding.ids.wedroid.app.data.entity.Board import it.unisannio.ding.ids.wedroid.app.data.entity.convert import it.unisannio.ding.ids.wedroid.app.util.PreferenceReader import it.unisannio.ding.ids.wedroid.wrapper.api.BoardService import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardBackgroundColor import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardPermission import it.unisannio.ding.ids.wedroid.wrapper.entity.BoardPrototype import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import retrofit2.Call import retrofit2.Callback import retrofit2.Response class BoardRepository( private val dao: BoardDao, private val service: BoardService, private val reader: PreferenceReader ) { val allBoards by lazy { dao.getAllBoard() } init { synchronize() } fun synchronize() { service.getBoardsFromUser(reader.userId) .enqueue(object : Callback> { override fun onFailure( call: Call>, t: Throwable ) = logNetworkError(t.message) override fun onResponse( call: Call>, response: Response> ) { CoroutineScope(Dispatchers.IO).launch { synchronizeCallback(response) } } }) } private suspend fun synchronizeCallback( response: Response> ) { if (!response.isSuccessful) { logNetworkError("${response.code()} ${response.message()}") return } // read boards from the body val boards = (response.body() ?: return) .map { it.convert() } addNewBoardToDb(boards) removeOldBoardsFromDb(boards) } fun insertBoard(title: String, isPrivate: Boolean, color: BoardBackgroundColor) { val permission = if (isPrivate) BoardPermission.PRIVATE else BoardPermission.PUBLIC service.newBoard( BoardPrototype.Builder() .setOwner(reader.userId) .setTitle(title) .setBackgroundColor(color) .setBoardPermission(permission) .build() ).enqueue(object : Callback { override fun onFailure( call: Call, t: Throwable ) = logNetworkError(t.message) override fun onResponse( call: Call, response: Response ) { CoroutineScope(Dispatchers.IO).launch { insertBoardCallback(response, title) } } }) } private suspend fun insertBoardCallback( response: Response, title: String ) { if (!response.isSuccessful) { logNetworkError("${response.code()} ${response.message()}") return } val board = response.body() if (board == null) { logNetworkError("empty body") return } dao.insert(Board(board.id, title)) } fun deleteBoard(id: String) { service.deleteBoard(id).enqueue( object : Callback { override fun onFailure(call: Call, t: Throwable) { logNetworkError(t.message) } override fun onResponse( call: Call, response: Response ) { CoroutineScope(Dispatchers.IO).launch { deleteBoardCallback(response, id) } } }) } private suspend fun deleteBoardCallback( response: Response, id: String ) { if (!response.isSuccessful) { logNetworkError("${response.code()} ${response.message()}") return } dao.delete(Board(id)) } private suspend fun addNewBoardToDb(boards: Collection) { boards.forEach { dao.insert(it) } } private suspend fun removeOldBoardsFromDb(boards: Collection) { allBoards.value?.minus(boards) ?.forEach { dao.delete(it) } } private fun logNetworkError(message: String?) { Log.e("RETROFIT", message) } }