package com.ustadmobile.core.db.dao

import androidx.lifecycle.LiveData
import androidx.paging.DataSource
import com.ustadmobile.door.DoorQuery
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.entities.ContentEntryStatementScoreProgress
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonWithAttemptsSummary
import com.ustadmobile.lib.db.entities.PersonWithSessionsDisplay
import com.ustadmobile.lib.db.entities.StatementEntity
import com.ustadmobile.lib.db.entities.StatementEntityWithDisplayDetails
import com.ustadmobile.lib.db.entities.StatementReportData
import com.ustadmobile.lib.db.entities.StatementWithSessionDetailDisplay
import com.ustadmobile.lib.db.entities.XLangMapEntry
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

public class StatementDao_ReplicateWrapper(
  private val _db: RoomDatabase,
  private val _dao: StatementDao,
) : StatementDao() {
  public override suspend fun replicateOnNewNode(newNodeId: Long): Unit {
    _dao.replicateOnNewNode(newNodeId)
  }

  public override suspend fun replicateOnChange(): Unit {
    _dao.replicateOnChange()
  }

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

  public override fun getOneStatement(): LiveData<StatementEntity?> = _dao.getOneStatement()

  public override fun findByStatementId(id: String): StatementEntity? = _dao.findByStatementId(id)

  public override fun findByStatementIdList(id: List<String>): List<StatementEntity> =
      _dao.findByStatementIdList(id)

  public override suspend fun getResults(query: DoorQuery): List<StatementReportData> =
      _dao.getResults(query)

  public override fun getListResults(query: DoorQuery):
      DataSource.Factory<Int, StatementEntityWithDisplayDetails> = _dao.getListResults(query)

  public override fun getPerson(): Person? = _dao.getPerson()

  public override fun getXLangMap(): XLangMapEntry? = _dao.getXLangMap()

  public override fun updateProgress(
    uid: Long,
    progress: Int,
    updateTime: Long,
  ): Unit {
    _dao.updateProgress(uid, progress, updateTime)
  }

  public override fun findPersonsWithContentEntryAttempts(
    contentEntryUid: Long,
    accountPersonUid: Long,
    searchText: String,
    sortOrder: Int,
  ): DataSource.Factory<Int, PersonWithAttemptsSummary> =
      _dao.findPersonsWithContentEntryAttempts(contentEntryUid, accountPersonUid, searchText,
      sortOrder)

  public override suspend fun getBestScoreForContentForPerson(contentEntryUid: Long,
      accountPersonUid: Long): ContentEntryStatementScoreProgress? =
      _dao.getBestScoreForContentForPerson(contentEntryUid, accountPersonUid)

  public override suspend fun findNextStudentNotMarkedForAssignment(assignmentUid: Long,
      currentStudentUid: Long): Long = _dao.findNextStudentNotMarkedForAssignment(assignmentUid,
      currentStudentUid)

  public override suspend fun findSubmittedStatementFromStudent(studentUid: Long,
      assignmentObjectUid: Long): StatementEntity? =
      _dao.findSubmittedStatementFromStudent(studentUid, assignmentObjectUid)

  public override fun findScoreStatementForStudent(studentUid: Long): StatementEntity? =
      _dao.findScoreStatementForStudent(studentUid)

  public override fun findSessionsForPerson(
    contentEntryUid: Long,
    accountPersonUid: Long,
    personUid: Long,
  ): DataSource.Factory<Int, PersonWithSessionsDisplay> =
      _dao.findSessionsForPerson(contentEntryUid, accountPersonUid, personUid)

  public override fun findSessionDetailForPerson(
    contentEntryUid: Long,
    accountPersonUid: Long,
    personUid: Long,
    contextRegistration: String,
  ): DataSource.Factory<Int, StatementWithSessionDetailDisplay> =
      _dao.findSessionDetailForPerson(contentEntryUid, accountPersonUid, personUid,
      contextRegistration)

  public override suspend fun calculateScoreForSession(contextRegistration: String):
      ContentEntryStatementScoreProgress? = _dao.calculateScoreForSession(contextRegistration)

  public override suspend fun findCompletedScoreForSession(contextRegistration: String):
      ContentEntryStatementScoreProgress? = _dao.findCompletedScoreForSession(contextRegistration)

  public override suspend fun findLatestRegistrationStatement(accountPersonUid: Long,
      entryUid: Long): String? = _dao.findLatestRegistrationStatement(accountPersonUid, entryUid)

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

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

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

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

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