package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.door.ext.doorPrimaryKeyManager
import com.ustadmobile.door.ext.rootDatabase
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.door.util.systemTimeInMillis
import com.ustadmobile.lib.db.composites.ClazzAndDetailPermissions
import com.ustadmobile.lib.db.composites.ClazzAndDisplayDetails
import com.ustadmobile.lib.db.composites.ClazzNameAndTerminology
import com.ustadmobile.lib.db.composites.ClazzUidAndName
import com.ustadmobile.lib.db.entities.Clazz
import com.ustadmobile.lib.db.entities.ClazzWithHolidayCalendarAndAndTerminology
import com.ustadmobile.lib.db.entities.ClazzWithListDisplayDetails
import com.ustadmobile.lib.db.entities.UidAndLabel
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public class ClazzDao_DoorWrapper(
  private val _db: RoomDatabase,
  private val _dao: ClazzDao,
) : ClazzDao() {
  override fun findByUid(uid: Long): Clazz? = _dao.findByUid(uid)

  override fun findByUidLive(uid: Long): Flow<Clazz?> = _dao.findByUidLive(uid)

  override suspend fun findByClazzCode(code: String): Clazz? = _dao.findByClazzCode(code)

  override suspend fun findByClazzCodeFromWeb(code: String): Clazz? =
      _dao.findByClazzCodeFromWeb(code)

  override fun findAllLive(): Flow<List<Clazz>> = _dao.findAllLive()

  override fun findAll(): List<Clazz> = _dao.findAll()

  override suspend fun findByUidAsync(clazzUid: Long): Clazz? = _dao.findByUidAsync(clazzUid)

  override suspend fun clazzUidExistsAsync(clazzUid: Long): Boolean =
      _dao.clazzUidExistsAsync(clazzUid)

  override fun findByUidAsFlow(uid: Long): Flow<Clazz?> = _dao.findByUidAsFlow(uid)

  override suspend fun findByUidWithHolidayCalendarAsync(uid: Long):
      ClazzWithHolidayCalendarAndAndTerminology? = _dao.findByUidWithHolidayCalendarAsync(uid)

  override suspend fun updateAsync(entity: Clazz): Int {
    entity.clazzLct = systemTimeInMillis()
    //must set versionid and/or primary key here
    return _dao.updateAsync(entity)
  }

  override fun findClazzesWithPermission(
    searchQuery: String,
    accountPersonUid: Long,
    excludeSelectedClazzList: List<Long>,
    sortOrder: Int,
    filter: Int,
    currentTime: Long,
    permission: Long,
  ): PagingSource<Int, ClazzWithListDisplayDetails> = _dao.findClazzesWithPermission(searchQuery,
      accountPersonUid, excludeSelectedClazzList, sortOrder, filter, currentTime, permission)

  override suspend fun getClassNamesFromListOfIds(ids: List<Long>): List<UidAndLabel> =
      _dao.getClassNamesFromListOfIds(ids)

  override fun findByClazzName(name: String): List<Clazz> = _dao.findByClazzName(name)

  override suspend fun updateClazzAttendanceAverageAsync(clazzUid: Long, timeChanged: Long) {
    _dao.updateClazzAttendanceAverageAsync(clazzUid, timeChanged)
  }

  override fun clazzAndDetailPermissionsAsFlow(accountPersonUid: Long, clazzUid: Long):
      Flow<ClazzAndDetailPermissions?> = _dao.clazzAndDetailPermissionsAsFlow(accountPersonUid,
      clazzUid)

  override fun getClazzWithDisplayDetails(
    clazzUid: Long,
    currentTime: Long,
    accountPersonUid: Long,
  ): Flow<ClazzAndDisplayDetails?> = _dao.getClazzWithDisplayDetails(clazzUid, currentTime,
      accountPersonUid)

  override fun findClazzesWithEffectiveHolidayCalendarAndFilter(filterUid: Long):
      List<ClazzWithHolidayCalendarAndAndTerminology> =
      _dao.findClazzesWithEffectiveHolidayCalendarAndFilter(filterUid)

  override fun getTitleByUidAsFlow(clazzUid: Long): Flow<String?> =
      _dao.getTitleByUidAsFlow(clazzUid)

  override fun getClazzNameAndTerminologyAsFlow(clazzUid: Long): Flow<ClazzNameAndTerminology?> =
      _dao.getClazzNameAndTerminologyAsFlow(clazzUid)

  override fun getClazzNameAsFlow(clazzUid: Long): Flow<String?> = _dao.getClazzNameAsFlow(clazzUid)

  override suspend fun getClazzTimeZoneByClazzUidAsync(clazzUid: Long): String? =
      _dao.getClazzTimeZoneByClazzUidAsync(clazzUid)

  override suspend fun getCoursesByName(names: List<String>): List<Clazz> =
      _dao.getCoursesByName(names)

  override suspend fun findOneRosterUserClazzes(accountPersonUid: Long,
      filterByEnrolledMemberPersonUid: Long): List<Clazz> =
      _dao.findOneRosterUserClazzes(accountPersonUid, filterByEnrolledMemberPersonUid)

  override suspend fun findClazzNamesByUids(uidList: List<Long>): List<ClazzUidAndName> =
      _dao.findClazzNamesByUids(uidList)

  public override fun insert(entity: Clazz): Long {
    val _pkManager = _db.rootDatabase.doorPrimaryKeyManager
    if(entity.clazzUid == 0L) {
      val _newPk = _pkManager.nextId(6)
      entity.clazzUid = _newPk
    }
    entity.clazzLct = systemTimeInMillis()
    //must set versionid and/or primary key here
    _dao.insert(entity)
    return entity.clazzUid
  }

  public override suspend fun insertAsync(entity: Clazz): Long {
    val _pkManager = _db.rootDatabase.doorPrimaryKeyManager
    if(entity.clazzUid == 0L) {
      val _newPk = _pkManager.nextIdAsync(6)
      entity.clazzUid = _newPk
    }
    entity.clazzLct = systemTimeInMillis()
    //must set versionid and/or primary key here
    _dao.insertAsync(entity)
    return entity.clazzUid
  }

  public override fun insertList(entityList: List<Clazz>) {
    val _pkManager = _db.rootDatabase.doorPrimaryKeyManager
    val _generatedPks = mutableListOf<Long>()
    entityList.iterator().forEach  {
      if(it.clazzUid == 0L) {
        val _newPk = _pkManager.nextId(6)
        it.clazzUid = _newPk
        _generatedPks += _newPk
      }
      it.clazzLct = systemTimeInMillis()
    }
    //must set versionid and/or primary key here
    _dao.insertList(entityList)
  }

  public override fun update(entity: Clazz) {
    entity.clazzLct = systemTimeInMillis()
    //must set versionid and/or primary key here
    _dao.update(entity)
  }
}
