package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
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.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

@Dao
public actual abstract class LanguageDao : BaseDao<Language> {
  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insertListAsync(languageList: List<Language>)

  @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):
      PagingSource<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(
    entity = Any::class,
    onConflict = 3,
  )
  actual abstract override fun update(entity: Language)

  @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(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun updateAsync(entity: Language): Int

  @Query(`value` = "SELECT * FROM LANGUAGE")
  public actual abstract fun findAllLanguageLive(): Flow<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,
  )

  @Insert(
    onConflict = 1,
    entity = Any::class,
  )
  public actual abstract fun replaceList(entityList: List<Language>)
}
