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.AssignmentSubmitterUidAndName
import com.ustadmobile.lib.db.composites.ClazzAssignmentAndBlock
import com.ustadmobile.lib.db.entities.AssignmentProgressSummary
import com.ustadmobile.lib.db.entities.AssignmentSubmitterSummary
import com.ustadmobile.lib.db.entities.ClazzAssignment
import com.ustadmobile.lib.db.entities.ClazzAssignmentCourseBlockAndSubmitterUid
import com.ustadmobile.lib.db.entities.ClazzEnrolment
import com.ustadmobile.lib.db.entities.CourseAssignmentMark
import com.ustadmobile.lib.db.entities.CourseAssignmentSubmission
import com.ustadmobile.lib.db.entities.CourseGroupMember
import com.ustadmobile.lib.db.entities.PeerReviewerAllocation
import kotlin.Boolean
import kotlin.IllegalStateException
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public class ClazzAssignmentDao_DoorWrapper(
  private val _db: RoomDatabase,
  private val _dao: ClazzAssignmentDao,
) : ClazzAssignmentDao() {
  override suspend fun getAllAssignmentsByClazzUidAsync(clazzUid: Long): List<ClazzAssignment> =
      _dao.getAllAssignmentsByClazzUidAsync(clazzUid)

  override suspend fun updateActiveByUid(
    cbUid: Long,
    active: Boolean,
    changeTime: Long,
  ) {
    _dao.updateActiveByUid(cbUid, active, changeTime)
  }

  override fun getProgressSummaryForAssignment(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
    group: String,
  ): Flow<AssignmentProgressSummary?> = _dao.getProgressSummaryForAssignment(assignmentUid,
      clazzUid, accountPersonUid, group)

  override fun getAssignmentSubmitterSummaryListForAssignment(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
    group: String,
    searchText: String,
    sortOption: Int,
  ): PagingSource<Int, AssignmentSubmitterSummary> =
      _dao.getAssignmentSubmitterSummaryListForAssignment(assignmentUid, clazzUid, accountPersonUid,
      group, searchText, sortOption)

  override suspend fun getCourseGroupMembersByAssignmentUid(assignmentUid: Long):
      List<CourseGroupMember> = _dao.getCourseGroupMembersByAssignmentUid(assignmentUid)

  override suspend fun getAssignmentSubmissionsByAssignmentUid(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
    group: String,
  ): List<CourseAssignmentSubmission> = _dao.getAssignmentSubmissionsByAssignmentUid(assignmentUid,
      clazzUid, accountPersonUid, group)

  override suspend fun getAssignmentMarksByAssignmentUid(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
    group: String,
  ): List<CourseAssignmentMark> = _dao.getAssignmentMarksByAssignmentUid(assignmentUid, clazzUid,
      accountPersonUid, group)

  override suspend fun getPeerReviewerAllocationsByAssignmentUid(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
  ): List<PeerReviewerAllocation> = _dao.getPeerReviewerAllocationsByAssignmentUid(assignmentUid,
      clazzUid, accountPersonUid)

  override suspend fun getPeerReviewAllocationsForPerson(assignmentUid: Long,
      accountPersonUid: Long): List<PeerReviewerAllocation> =
      _dao.getPeerReviewAllocationsForPerson(assignmentUid, accountPersonUid)

  override suspend fun getSubmitterUidsByClazzOrGroupSetUid(
    clazzUid: Long,
    groupSetUid: Long,
    time: Long,
  ): List<Long> = _dao.getSubmitterUidsByClazzOrGroupSetUid(clazzUid, groupSetUid, time)

  override suspend fun getSubmitterUidsAndNameByClazzOrGroupSetUid(
    clazzUid: Long,
    groupSetUid: Long,
    date: Long,
    groupStr: String,
  ): List<AssignmentSubmitterUidAndName> =
      _dao.getSubmitterUidsAndNameByClazzOrGroupSetUid(clazzUid, groupSetUid, date, groupStr)

  override suspend fun getSubmitterCountFromAssignment(
    groupUid: Long,
    clazzUid: Long,
    group: String,
  ): Int = _dao.getSubmitterCountFromAssignment(groupUid, clazzUid, group)

  override suspend fun getSubmitterUid(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
  ): Long = _dao.getSubmitterUid(assignmentUid, clazzUid, accountPersonUid)

  override suspend fun updateAsync(clazzAssignment: ClazzAssignment) {
    clazzAssignment.caLct = systemTimeInMillis()
    //must set versionid and/or primary key here
    _dao.updateAsync(clazzAssignment)
  }

  override suspend fun findByUidAsync(uid: Long): ClazzAssignment? = _dao.findByUidAsync(uid)

  override fun findByUidAndClazzUidAsFlow(uid: Long, clazzUid: Long): Flow<ClazzAssignment?> =
      _dao.findByUidAndClazzUidAsFlow(uid, clazzUid)

  override suspend fun findByUidAndClazzUidAsync(assignmentUid: Long, clazzUid: Long):
      ClazzAssignment? = _dao.findByUidAndClazzUidAsync(assignmentUid, clazzUid)

  override suspend fun getGroupUidFromAssignment(uid: Long): Long =
      _dao.getGroupUidFromAssignment(uid)

  override suspend fun getMarkingTypeFromAssignment(uid: Long): Int =
      _dao.getMarkingTypeFromAssignment(uid)

  override suspend fun findByUidWithBlockAsync(uid: Long): ClazzAssignmentAndBlock? =
      _dao.findByUidWithBlockAsync(uid)

  override fun findClazzAssignment(): ClazzAssignment? = throw
      IllegalStateException("findClazzAssignment: synchronous db access is NOT possible on Javascript!")

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

  override suspend fun upsertListAsync(entities: List<ClazzAssignment>) {
    val _pkManager = _db.rootDatabase.doorPrimaryKeyManager
    val _generatedPks = mutableListOf<Long>()
    entities.iterator().forEach  {
      if(it.caUid == 0L) {
        val _newPk = _pkManager.nextIdAsync(520)
        it.caUid = _newPk
        _generatedPks += _newPk
      }
      it.caLct = systemTimeInMillis()
    }
    //must set versionid and/or primary key here
    _dao.upsertListAsync(entities)
  }

  override suspend fun updateActiveByList(
    uidList: List<Long>,
    active: Boolean,
    changeTime: Long,
  ) {
    _dao.updateActiveByList(uidList, active, changeTime)
  }

  override fun findAssignmentCourseBlockAndSubmitterUidAsFlow(
    assignmentUid: Long,
    clazzUid: Long,
    accountPersonUid: Long,
  ): Flow<ClazzAssignmentCourseBlockAndSubmitterUid?> =
      _dao.findAssignmentCourseBlockAndSubmitterUidAsFlow(assignmentUid, clazzUid, accountPersonUid)

  override suspend fun findEnrolmentsByPersonUidAndAssignmentUid(assignmentUid: Long,
      accountPersonUid: Long): List<ClazzEnrolment> =
      _dao.findEnrolmentsByPersonUidAndAssignmentUid(assignmentUid, accountPersonUid)

  override suspend fun findCourseGroupMembersByPersonUidAndAssignmentUid(assignmentUid: Long,
      accountPersonUid: Long): List<CourseGroupMember> =
      _dao.findCourseGroupMembersByPersonUidAndAssignmentUid(assignmentUid, accountPersonUid)

  override suspend fun findPeerReviewerAllocationsByPersonUidAndAssignmentUid(assignmentUid: Long,
      accountPersonUid: Long): List<PeerReviewerAllocation> =
      _dao.findPeerReviewerAllocationsByPersonUidAndAssignmentUid(assignmentUid, accountPersonUid)

  override suspend fun getLatestSubmissionTimeAllowed(assignmentUid: Long): Long =
      _dao.getLatestSubmissionTimeAllowed(assignmentUid)

  public override fun insert(entity: ClazzAssignment): Long = throw
      IllegalStateException("insert: synchronous db access is NOT possible on Javascript!")

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

  public override fun insertList(entityList: List<ClazzAssignment>): Unit = throw
      IllegalStateException("insertList: synchronous db access is NOT possible on Javascript!")

  public override fun update(entity: ClazzAssignment): Unit = throw
      IllegalStateException("update: synchronous db access is NOT possible on Javascript!")

  public override suspend fun insertListAsync(entityList: List<ClazzAssignment>) {
    val _pkManager = _db.rootDatabase.doorPrimaryKeyManager
    val _generatedPks = mutableListOf<Long>()
    entityList.iterator().forEach  {
      if(it.caUid == 0L) {
        val _newPk = _pkManager.nextIdAsync(520)
        it.caUid = _newPk
        _generatedPks += _newPk
      }
      it.caLct = systemTimeInMillis()
    }
    //must set versionid and/or primary key here
    _dao.insertListAsync(entityList)
  }

  public override suspend fun updateListAsync(entityList: List<ClazzAssignment>) {
    val _generatedPks = mutableListOf<Long>()
    entityList.iterator().forEach  {
      it.caLct = systemTimeInMillis()
    }
    //must set versionid and/or primary key here
    _dao.updateListAsync(entityList)
  }
}
