package com.ustadmobile.core.db.dao

import androidx.lifecycle.LiveData
import androidx.paging.DataSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.ustadmobile.lib.db.entities.HolidayCalendar
import com.ustadmobile.lib.db.entities.HolidayCalendarWithNumEntries
import kotlin.Int
import kotlin.Long
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class HolidayCalendarDao : BaseDao<HolidayCalendar> {
  @Query(`value` =
      "\n     REPLACE INTO HolidayCalendarReplicate(hcPk, hcDestination)\n      SELECT DISTINCT HolidayCalendar.umCalendarUid AS hcPk,\n             :newNodeId AS hcDestination\n        FROM HolidayCalendar\n             JOIN UserSession\n                  ON UserSession.usClientNodeId = :newNodeId\n        --notpsql \n       WHERE HolidayCalendar.umCalendarLct != COALESCE(\n             (SELECT hcVersionId\n                FROM HolidayCalendarReplicate\n               WHERE hcPk = HolidayCalendar.umCalendarUid\n                 AND hcDestination = UserSession.usClientNodeId), 0) \n         --endnotpsql        \n      /*psql ON CONFLICT(hcPk, hcDestination) DO UPDATE\n             SET hcPending = (SELECT HolidayCalendar.umCalendarLct\n                                FROM HolidayCalendar\n                               WHERE HolidayCalendar.umCalendarUid = EXCLUDED.hcPk ) \n                                     != HolidayCalendarReplicate.hcPk\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n REPLACE INTO HolidayCalendarReplicate(hcPk, hcDestination)\n  SELECT DISTINCT HolidayCalendar.umCalendarUid AS hcUid,\n         UserSession.usClientNodeId AS hcDestination\n    FROM ChangeLog\n         JOIN HolidayCalendar\n             ON ChangeLog.chTableId = 28\n                AND ChangeLog.chEntityPk = HolidayCalendar.umCalendarUid\n         JOIN UserSession ON UserSession.usStatus = 1\n   WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     --notpsql \n      AND HolidayCalendar.umCalendarLct != COALESCE(\n             (SELECT hcVersionId\n                FROM HolidayCalendarReplicate\n               WHERE hcPk = HolidayCalendar.umCalendarUid\n                 AND hcDestination = UserSession.usClientNodeId), 0) \n         --endnotpsql    \n   /*psql ON CONFLICT(hcPk, hcDestination) DO UPDATE\n             SET hcPending = (SELECT HolidayCalendar.umCalendarLct\n                                FROM HolidayCalendar\n                               WHERE HolidayCalendar.umCalendarUid = EXCLUDED.hcPk ) \n                                     != HolidayCalendarReplicate.hcPk     \n        */                                           \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Query(`value` =
      "SELECT HolidayCalendar.* ,\n            (SELECT COUNT(*) FROM Holiday \n               WHERE holHolidayCalendarUid = HolidayCalendar.umCalendarUid \n               AND CAST(holActive AS INTEGER) = 1) AS numEntries \n             FROM HolidayCalendar WHERE CAST(umCalendarActive AS INTEGER) = 1 AND \n             umCalendarCategory = 1")
  public actual abstract fun findAllHolidaysWithEntriesCount():
      DataSource.Factory<Int, HolidayCalendarWithNumEntries>

  @Insert(onConflict = 1)
  public actual abstract fun replaceList(list: List<HolidayCalendar>): Unit

  @Query(`value` =
      "SELECT * FROM HolidayCalendar WHERE CAST(umCalendarActive AS INTEGER) = 1 AND umCalendarCategory = 1")
  public actual abstract fun findAllHolidaysLiveData(): LiveData<List<HolidayCalendar>>

  @Query(`value` =
      "SELECT * FROM HolidayCalendar WHERE umCalendarUid = :uid AND CAST(umCalendarActive AS INTEGER) = 1")
  public actual abstract fun findByUidLive(uid: Long): LiveData<HolidayCalendar?>

  @Update(onConflict = 3)
  public actual abstract suspend fun updateAsync(entity: HolidayCalendar): Int

  @Query(`value` = "SELECT * FROM HolidayCalendar WHERE umCalendarUid = :uid")
  public actual abstract suspend fun findByUid(uid: Long): HolidayCalendar?

  @Query(`value` = "SELECT * FROM HolidayCalendar WHERE umCalendarUid = :uid")
  public actual abstract suspend fun findByUidAsync(uid: Long): HolidayCalendar?
}
