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.Language
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class LanguageDao : BaseDao<Language> {
  @Query(`value` =
      "\n     REPLACE INTO LanguageReplicate(languagePk, languageDestination)\n      SELECT DISTINCT Language.langUid AS languagePk,\n             :newNodeId AS languageDestination\n        FROM Language\n       WHERE Language.langLct != COALESCE(\n             (SELECT languageVersionId\n                FROM LanguageReplicate\n               WHERE languagePk = Language.langUid\n                 AND languageDestination = :newNodeId), 0) \n      /*psql ON CONFLICT(languagePk, languageDestination) DO UPDATE\n             SET languagePending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n REPLACE INTO LanguageReplicate(languagePk, languageDestination)\n  SELECT DISTINCT Language.langUid AS languageUid,\n         UserSession.usClientNodeId AS languageDestination\n    FROM ChangeLog\n         JOIN Language\n             ON ChangeLog.chTableId = 13\n                AND ChangeLog.chEntityPk = Language.langUid\n         JOIN UserSession ON UserSession.usStatus = 1\n   WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     AND Language.langLct != COALESCE(\n         (SELECT languageVersionId\n            FROM LanguageReplicate\n           WHERE languagePk = Language.langUid\n             AND languageDestination = UserSession.usClientNodeId), 0)\n /*psql ON CONFLICT(languagePk, languageDestination) DO UPDATE\n     SET languagePending = true\n  */               \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Insert(onConflict = 3)
  public actual abstract suspend fun insertListAsync(languageList: List<Language>): Unit

  @Query(`value` =
      "\n        SELECT Language.* \n        FROM Language\n        WHERE name LIKE :searchText\n        ORDER BY CASE(:sortOrder)\n            WHEN 1 THEN Language.name \n            WHEN 3 THEN Language.iso_639_1_standard \n            WHEN 5 THEN Language.iso_639_2_standard \n            ELSE ''\n        END ASC,\n        CASE(:sortOrder)\n            WHEN 2 THEN Language.name \n            WHEN 4 THEN Language.iso_639_1_standard \n            WHEN 6 THEN Language.iso_639_2_standard \n            ELSE ''\n        END DESC\n    ")
  public actual abstract fun findLanguagesAsSource(sortOrder: Int, searchText: String):
      DataSource.Factory<Int, Language>

  @Query(`value` = "SELECT * FROM Language")
  public actual abstract fun findLanguagesList(): List<Language>

  @Query(`value` = "SELECT * FROM Language WHERE name = :name LIMIT 1")
  public actual abstract fun findByName(name: String): Language?

  @Query(`value` = "SELECT * FROM Language WHERE iso_639_1_standard = :langCode LIMIT 1")
  public actual abstract fun findByTwoCode(langCode: String): Language?

  @Query(`value` = "SELECT * FROM Language WHERE iso_639_1_standard = :langCode LIMIT 1")
  public actual abstract suspend fun findByTwoCodeAsync(langCode: String): Language?

  @Query(`value` =
      "SELECT * FROM LANGUAGE WHERE iso_639_3_standard = :langCode OR iso_639_2_standard = :langCode LIMIT 1 ")
  public actual abstract fun findByThreeCode(langCode: String): Language?

  @Query(`value` = "SELECT COUNT(*) FROM LANGUAGE")
  public actual abstract fun totalLanguageCount(): Int

  @Update(onConflict = 3)
  public actual abstract override fun update(entity: Language): Unit

  @Query(`value` = "SELECT *  FROM LANGUAGE where langUid = :primaryLanguageUid LIMIT 1")
  public actual abstract fun findByUid(primaryLanguageUid: Long): Language?

  @Query(`value` = "SELECT *  FROM LANGUAGE where langUid = :primaryLanguageUid LIMIT 1")
  public actual abstract suspend fun findByUidAsync(primaryLanguageUid: Long): Language?

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

  @Query(`value` = "SELECT * FROM LANGUAGE")
  public actual abstract fun findAllLanguageLive(): LiveData<List<Language>>

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

  @Query(`value` =
      "\n        UPDATE Language \n           SET languageActive = :toggleVisibility, \n               langLct = :updateTime\n         WHERE langUid IN (:selectedItem)")
  public actual abstract suspend fun toggleVisibilityLanguage(
    toggleVisibility: Boolean,
    selectedItem: List<Long>,
    updateTime: Long,
  ): Unit

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