package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.lib.db.composites.PersonAndListDisplayDetails
import com.ustadmobile.lib.db.composites.PersonAndPicture
import com.ustadmobile.lib.db.composites.PersonNames
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonAndDisplayDetail
import com.ustadmobile.lib.db.entities.PersonAuth
import com.ustadmobile.lib.db.entities.PersonGroup
import com.ustadmobile.lib.db.entities.PersonGroupMember
import com.ustadmobile.lib.db.entities.PersonUidAndPasswordHash
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public actual abstract class PersonDao : BaseDao<Person> {
  public actual abstract suspend fun insertListAsync(entityList: List<Person>)

  public actual abstract suspend fun insertOrReplace(person: Person)

  public actual abstract suspend fun countUsername(username: String): Int

  public actual abstract suspend fun findUidAndPasswordHashAsync(username: String):
      PersonUidAndPasswordHash?

  public actual abstract suspend fun findByUsernameAndPasswordHash2(username: String,
      passwordHash: String): Person?

  public actual abstract fun insertPersonAuth(personAuth: PersonAuth)

  public actual abstract fun findByUsername(username: String?): Person?

  public actual abstract suspend fun findByUsernameAsync(username: String): Person?

  public actual abstract suspend fun findSystemAccount(nodeId: Long): Person?

  public actual abstract fun findByUid(uid: Long): Person?

  public actual abstract suspend fun findByUidWithPicture(accountPersonUid: Long): PersonAndPicture?

  public actual abstract fun findByUidWithPictureAsFlow(uid: Long): Flow<PersonAndPicture?>

  public actual abstract fun findByUidLive(uid: Long): Flow<Person?>

  public actual abstract suspend fun findByUidAsync(uid: Long): Person?

  public actual abstract fun findByUidAsFlow(uid: Long): Flow<Person?>

  public actual abstract suspend fun updateAsync(entity: Person): Int

  public actual abstract suspend fun insertPersonGroup(personGroup: PersonGroup): Long

  public actual abstract suspend fun insertPersonGroupMember(personGroupMember: PersonGroupMember):
      Long

  public actual abstract fun findPersonsWithPermissionAsList(
    timestamp: Long,
    excludeClazz: Long,
    excludeSelected: List<Long>,
    accountPersonUid: Long,
    sortOrder: Int,
    searchText: String?,
  ): List<PersonAndListDisplayDetails>

  public actual abstract fun findPersonsWithPermissionAsPagingSource(
    timestamp: Long,
    excludeClazz: Long,
    excludeSelected: List<Long>,
    accountPersonUid: Long,
    sortOrder: Int,
    searchText: String?,
  ): PagingSource<Int, PersonAndListDisplayDetails>

  public actual abstract fun findByUidWithDisplayDetailsLive(personUid: Long,
      activeUserPersonUid: Long): Flow<PersonAndDisplayDetail?>

  public actual abstract fun findByUidWithDisplayDetailsFlow(personUid: Long,
      accountPersonUid: Long): Flow<PersonAndDisplayDetail?>

  public actual abstract fun getAllPerson(): List<Person>

  public actual abstract fun getNamesByUid(uid: Long): Flow<PersonNames?>

  public actual abstract suspend fun getNamesByUidAsync(uid: Long): PersonNames?

  public actual abstract suspend fun updateUsername(
    personUid: Long,
    username: String,
    currentTime: Long,
  ): Int

  public actual abstract suspend fun selectExistingUsernames(usernames: List<String>): List<String?>
}
