package com.ustadmobile.core.db.dao

import androidx.paging.DataSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.VerbDisplay
import com.ustadmobile.lib.db.entities.VerbEntity
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class VerbDao : BaseDao<VerbEntity> {
  @Query(`value` =
      "\n     REPLACE INTO VerbEntityReplicate(vePk, veDestination)\n      SELECT DISTINCT VerbEntity.verbUid AS vePk,\n             :newNodeId AS veDestination\n        FROM VerbEntity\n       WHERE VerbEntity.verbLct != COALESCE(\n             (SELECT veVersionId\n                FROM VerbEntityReplicate\n               WHERE vePk = VerbEntity.verbUid\n                 AND veDestination = :newNodeId), 0) \n      /*psql ON CONFLICT(vePk, veDestination) DO UPDATE\n             SET vePending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n    REPLACE INTO VerbEntityReplicate(vePk, veDestination)\n    SELECT DISTINCT VerbEntity.verbUid AS veUid,\n         UserSession.usClientNodeId AS veDestination\n    FROM ChangeLog\n         JOIN VerbEntity\n             ON ChangeLog.chTableId = 62\n                AND ChangeLog.chEntityPk = VerbEntity.verbUid\n         JOIN UserSession ON UserSession.usStatus = 1\n    WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     AND VerbEntity.verbLct != COALESCE(\n         (SELECT veVersionId\n            FROM VerbEntityReplicate\n           WHERE vePk = VerbEntity.verbUid\n             AND veDestination = UserSession.usClientNodeId), 0)\n    /*psql ON CONFLICT(vePk, veDestination) DO UPDATE\n     SET vePending = true\n    */               \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Query(`value` = "SELECT * FROM VerbEntity WHERE urlId = :urlId")
  public actual abstract fun findByUrl(urlId: String?): VerbEntity?

  @Query(`value` = "SELECT verbUid FROM VerbEntity WHERE verbUid IN (:uidList)")
  public actual abstract suspend fun findByUidList(uidList: List<Long>): List<Long>

  @Insert(onConflict = 1)
  public actual abstract suspend fun replaceList(entityList: List<VerbEntity>): Unit

  @Query(`value` =
      "SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display\n        FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE \n         XLangMapEntry.verbLangMapUid NOT IN (:uidList)")
  public actual abstract fun findAllVerbsAscList(uidList: List<Long>): List<VerbDisplay>

  @Query(`value` =
      "SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display \n         FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE \n         VerbEntity.verbUid NOT IN (:uidList) ORDER BY display ASC")
  public actual abstract fun findAllVerbsAsc(uidList: List<Long>):
      DataSource.Factory<Int, VerbDisplay>

  @Query(`value` =
      "SELECT VerbEntity.verbUid, VerbEntity.urlId, XLangMapEntry.valueLangMap AS display \n         FROM VerbEntity LEFT JOIN XLangMapEntry on XLangMapEntry.verbLangMapUid = VerbEntity.verbUid WHERE \n        VerbEntity.verbUid NOT IN (:uidList) ORDER BY display DESC")
  public actual abstract fun findAllVerbsDesc(uidList: List<Long>):
      DataSource.Factory<Int, VerbDisplay>
}
