package com.ustadmobile.libcache.db.dao

import androidx.room.EntityInsertAdapter
import androidx.room.RoomDatabase
import androidx.room.coroutines.createFlow
import androidx.room.util.getColumnIndexOrThrow
import androidx.room.util.performSuspending
import androidx.sqlite.SQLiteStatement
import com.ustadmobile.libcache.PublicationPinState
import com.ustadmobile.libcache.db.DbTypeConverters
import com.ustadmobile.libcache.db.entities.DownloadJobItem
import io.ktor.http.Url
import javax.`annotation`.processing.Generated
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.List
import kotlin.collections.MutableList
import kotlin.collections.mutableListOf
import kotlin.reflect.KClass
import kotlinx.coroutines.flow.Flow

@Generated(value = ["androidx.room.RoomProcessor"])
@Suppress(names = ["UNCHECKED_CAST", "DEPRECATION", "REDUNDANT_PROJECTION", "REMOVAL"])
public class DownloadJobItemDao_Impl(
  __db: RoomDatabase,
) : DownloadJobItemDao() {
  private val __db: RoomDatabase

  private val __insertAdapterOfDownloadJobItem: EntityInsertAdapter<DownloadJobItem>

  private val __dbTypeConverters: DbTypeConverters = DbTypeConverters()
  init {
    this.__db = __db
    this.__insertAdapterOfDownloadJobItem = object : EntityInsertAdapter<DownloadJobItem>() {
      protected override fun createQuery(): String = "INSERT OR REPLACE INTO `DownloadJobItem` (`djiUid`,`djiDjUid`,`djiTotalSize`,`djiTransferred`,`djiAttemptCount`,`djiUrl`,`djiDest`,`djiType`,`djiStatus`,`djiEntityEtag`,`djiLockIdToRelease`,`djiPartialTmpFile`) VALUES (nullif(?, 0),?,?,?,?,?,?,?,?,?,?,?)"

      protected override fun bind(statement: SQLiteStatement, entity: DownloadJobItem) {
        statement.bindLong(1, entity.djiUid.toLong())
        statement.bindLong(2, entity.djiDjUid.toLong())
        statement.bindLong(3, entity.djiTotalSize)
        statement.bindLong(4, entity.djiTransferred)
        statement.bindLong(5, entity.djiAttemptCount.toLong())
        val _tmp: String? = __dbTypeConverters.fromUrl(entity.djiUrl)
        if (_tmp == null) {
          statement.bindNull(6)
        } else {
          statement.bindText(6, _tmp)
        }
        val _tmpDjiDest: String? = entity.djiDest
        if (_tmpDjiDest == null) {
          statement.bindNull(7)
        } else {
          statement.bindText(7, _tmpDjiDest)
        }
        statement.bindLong(8, entity.djiType.toLong())
        statement.bindLong(9, entity.djiStatus.toLong())
        statement.bindLong(10, entity.djiEntityEtag)
        statement.bindLong(11, entity.djiLockIdToRelease)
        val _tmpDjiPartialTmpFile: String? = entity.djiPartialTmpFile
        if (_tmpDjiPartialTmpFile == null) {
          statement.bindNull(12)
        } else {
          statement.bindText(12, _tmpDjiPartialTmpFile)
        }
      }
    }
  }

  public override suspend fun upsertList(items: List<DownloadJobItem>): Unit = performSuspending(__db, false, true) { _connection ->
    __insertAdapterOfDownloadJobItem.insert(_connection, items)
  }

  public override suspend fun findPendingByJobUid(jobUid: Int): List<DownloadJobItem> {
    val _sql: String = """
        |
        |        SELECT DownloadJobItem.*
        |          FROM DownloadJobItem
        |         WHERE DownloadJobItem.djiDjUid = ?
        |           AND DownloadJobItem.djiStatus < 21
        |    
        """.trimMargin()
    return performSuspending(__db, true, false) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, jobUid.toLong())
        val _columnIndexOfDjiUid: Int = getColumnIndexOrThrow(_stmt, "djiUid")
        val _columnIndexOfDjiDjUid: Int = getColumnIndexOrThrow(_stmt, "djiDjUid")
        val _columnIndexOfDjiTotalSize: Int = getColumnIndexOrThrow(_stmt, "djiTotalSize")
        val _columnIndexOfDjiTransferred: Int = getColumnIndexOrThrow(_stmt, "djiTransferred")
        val _columnIndexOfDjiAttemptCount: Int = getColumnIndexOrThrow(_stmt, "djiAttemptCount")
        val _columnIndexOfDjiUrl: Int = getColumnIndexOrThrow(_stmt, "djiUrl")
        val _columnIndexOfDjiDest: Int = getColumnIndexOrThrow(_stmt, "djiDest")
        val _columnIndexOfDjiType: Int = getColumnIndexOrThrow(_stmt, "djiType")
        val _columnIndexOfDjiStatus: Int = getColumnIndexOrThrow(_stmt, "djiStatus")
        val _columnIndexOfDjiEntityEtag: Int = getColumnIndexOrThrow(_stmt, "djiEntityEtag")
        val _columnIndexOfDjiLockIdToRelease: Int = getColumnIndexOrThrow(_stmt, "djiLockIdToRelease")
        val _columnIndexOfDjiPartialTmpFile: Int = getColumnIndexOrThrow(_stmt, "djiPartialTmpFile")
        val _result: MutableList<DownloadJobItem> = mutableListOf()
        while (_stmt.step()) {
          val _item: DownloadJobItem
          val _tmpDjiUid: Int
          _tmpDjiUid = _stmt.getLong(_columnIndexOfDjiUid).toInt()
          val _tmpDjiDjUid: Int
          _tmpDjiDjUid = _stmt.getLong(_columnIndexOfDjiDjUid).toInt()
          val _tmpDjiTotalSize: Long
          _tmpDjiTotalSize = _stmt.getLong(_columnIndexOfDjiTotalSize)
          val _tmpDjiTransferred: Long
          _tmpDjiTransferred = _stmt.getLong(_columnIndexOfDjiTransferred)
          val _tmpDjiAttemptCount: Int
          _tmpDjiAttemptCount = _stmt.getLong(_columnIndexOfDjiAttemptCount).toInt()
          val _tmpDjiUrl: Url
          val _tmp: String?
          if (_stmt.isNull(_columnIndexOfDjiUrl)) {
            _tmp = null
          } else {
            _tmp = _stmt.getText(_columnIndexOfDjiUrl)
          }
          val _tmp_1: Url? = __dbTypeConverters.toUrl(_tmp)
          if (_tmp_1 == null) {
            error("Expected NON-NULL 'io.ktor.http.Url', but it was NULL.")
          } else {
            _tmpDjiUrl = _tmp_1
          }
          val _tmpDjiDest: String?
          if (_stmt.isNull(_columnIndexOfDjiDest)) {
            _tmpDjiDest = null
          } else {
            _tmpDjiDest = _stmt.getText(_columnIndexOfDjiDest)
          }
          val _tmpDjiType: Int
          _tmpDjiType = _stmt.getLong(_columnIndexOfDjiType).toInt()
          val _tmpDjiStatus: Int
          _tmpDjiStatus = _stmt.getLong(_columnIndexOfDjiStatus).toInt()
          val _tmpDjiEntityEtag: Long
          _tmpDjiEntityEtag = _stmt.getLong(_columnIndexOfDjiEntityEtag)
          val _tmpDjiLockIdToRelease: Long
          _tmpDjiLockIdToRelease = _stmt.getLong(_columnIndexOfDjiLockIdToRelease)
          val _tmpDjiPartialTmpFile: String?
          if (_stmt.isNull(_columnIndexOfDjiPartialTmpFile)) {
            _tmpDjiPartialTmpFile = null
          } else {
            _tmpDjiPartialTmpFile = _stmt.getText(_columnIndexOfDjiPartialTmpFile)
          }
          _item = DownloadJobItem(_tmpDjiUid,_tmpDjiDjUid,_tmpDjiTotalSize,_tmpDjiTransferred,_tmpDjiAttemptCount,_tmpDjiUrl,_tmpDjiDest,_tmpDjiType,_tmpDjiStatus,_tmpDjiEntityEtag,_tmpDjiLockIdToRelease,_tmpDjiPartialTmpFile)
          _result.add(_item)
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun findAllByJobUid(jobUid: Int): List<DownloadJobItem> {
    val _sql: String = """
        |
        |        SELECT DownloadJobItem.*
        |          FROM DownloadJobItem
        |         WHERE DownloadJobItem.djiDjUid = ?
        |    
        """.trimMargin()
    return performSuspending(__db, true, false) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, jobUid.toLong())
        val _columnIndexOfDjiUid: Int = getColumnIndexOrThrow(_stmt, "djiUid")
        val _columnIndexOfDjiDjUid: Int = getColumnIndexOrThrow(_stmt, "djiDjUid")
        val _columnIndexOfDjiTotalSize: Int = getColumnIndexOrThrow(_stmt, "djiTotalSize")
        val _columnIndexOfDjiTransferred: Int = getColumnIndexOrThrow(_stmt, "djiTransferred")
        val _columnIndexOfDjiAttemptCount: Int = getColumnIndexOrThrow(_stmt, "djiAttemptCount")
        val _columnIndexOfDjiUrl: Int = getColumnIndexOrThrow(_stmt, "djiUrl")
        val _columnIndexOfDjiDest: Int = getColumnIndexOrThrow(_stmt, "djiDest")
        val _columnIndexOfDjiType: Int = getColumnIndexOrThrow(_stmt, "djiType")
        val _columnIndexOfDjiStatus: Int = getColumnIndexOrThrow(_stmt, "djiStatus")
        val _columnIndexOfDjiEntityEtag: Int = getColumnIndexOrThrow(_stmt, "djiEntityEtag")
        val _columnIndexOfDjiLockIdToRelease: Int = getColumnIndexOrThrow(_stmt, "djiLockIdToRelease")
        val _columnIndexOfDjiPartialTmpFile: Int = getColumnIndexOrThrow(_stmt, "djiPartialTmpFile")
        val _result: MutableList<DownloadJobItem> = mutableListOf()
        while (_stmt.step()) {
          val _item: DownloadJobItem
          val _tmpDjiUid: Int
          _tmpDjiUid = _stmt.getLong(_columnIndexOfDjiUid).toInt()
          val _tmpDjiDjUid: Int
          _tmpDjiDjUid = _stmt.getLong(_columnIndexOfDjiDjUid).toInt()
          val _tmpDjiTotalSize: Long
          _tmpDjiTotalSize = _stmt.getLong(_columnIndexOfDjiTotalSize)
          val _tmpDjiTransferred: Long
          _tmpDjiTransferred = _stmt.getLong(_columnIndexOfDjiTransferred)
          val _tmpDjiAttemptCount: Int
          _tmpDjiAttemptCount = _stmt.getLong(_columnIndexOfDjiAttemptCount).toInt()
          val _tmpDjiUrl: Url
          val _tmp: String?
          if (_stmt.isNull(_columnIndexOfDjiUrl)) {
            _tmp = null
          } else {
            _tmp = _stmt.getText(_columnIndexOfDjiUrl)
          }
          val _tmp_1: Url? = __dbTypeConverters.toUrl(_tmp)
          if (_tmp_1 == null) {
            error("Expected NON-NULL 'io.ktor.http.Url', but it was NULL.")
          } else {
            _tmpDjiUrl = _tmp_1
          }
          val _tmpDjiDest: String?
          if (_stmt.isNull(_columnIndexOfDjiDest)) {
            _tmpDjiDest = null
          } else {
            _tmpDjiDest = _stmt.getText(_columnIndexOfDjiDest)
          }
          val _tmpDjiType: Int
          _tmpDjiType = _stmt.getLong(_columnIndexOfDjiType).toInt()
          val _tmpDjiStatus: Int
          _tmpDjiStatus = _stmt.getLong(_columnIndexOfDjiStatus).toInt()
          val _tmpDjiEntityEtag: Long
          _tmpDjiEntityEtag = _stmt.getLong(_columnIndexOfDjiEntityEtag)
          val _tmpDjiLockIdToRelease: Long
          _tmpDjiLockIdToRelease = _stmt.getLong(_columnIndexOfDjiLockIdToRelease)
          val _tmpDjiPartialTmpFile: String?
          if (_stmt.isNull(_columnIndexOfDjiPartialTmpFile)) {
            _tmpDjiPartialTmpFile = null
          } else {
            _tmpDjiPartialTmpFile = _stmt.getText(_columnIndexOfDjiPartialTmpFile)
          }
          _item = DownloadJobItem(_tmpDjiUid,_tmpDjiDjUid,_tmpDjiTotalSize,_tmpDjiTransferred,_tmpDjiAttemptCount,_tmpDjiUrl,_tmpDjiDest,_tmpDjiType,_tmpDjiStatus,_tmpDjiEntityEtag,_tmpDjiLockIdToRelease,_tmpDjiPartialTmpFile)
          _result.add(_item)
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun findNumberJobItemsNotComplete(jobUid: Int): Int {
    val _sql: String = """
        |
        |       SELECT COUNT(*)
        |         FROM DownloadJobItem
        |        WHERE DownloadJobItem.djiDjUid = ?
        |          AND DownloadJobItem.djiStatus != 21
        |    
        """.trimMargin()
    return performSuspending(__db, true, false) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, jobUid.toLong())
        val _result: Int
        if (_stmt.step()) {
          val _tmp: Int
          _tmp = _stmt.getLong(0).toInt()
          _result = _tmp
        } else {
          _result = 0
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override fun publicationPinState(pubManifestHash: Long): Flow<PublicationPinState> {
    val _sql: String = """
        |
        |        WITH MostRecentDlUid(uid) AS (
        |            SELECT COALESCE(
        |                   (SELECT DownloadJob.djUid
        |                      FROM DownloadJob
        |                     WHERE DownloadJob.djPubManifestHash = ?
        |                  ORDER BY DownloadJob.djTimeCreated DESC
        |                     LIMIT 1), 0)
        |        )
        |        
        |        SELECT CASE((SELECT DownloadJob.djStatus
        |                       FROM DownloadJob
        |                      WHERE DownloadJob.djUid = (SELECT uid FROM MostRecentDlUid)))
        |                   WHEN 21 THEN 10
        |                   WHEN 11 THEN 3
        |                   WHEN 2 THEN 2
        |                   ELSE 0
        |                   END AS status,
        |               (SELECT SUM(DownloadJobItem.djiTransferred)
        |                  FROM DownloadJobItem
        |                 WHERE DownloadJobItem.djiDjUid = (SELECT uid FROM MostRecentDlUid)) AS transferred,
        |               (SELECT SUM(DownloadJobItem.djiTotalSize)
        |                  FROM DownloadJobItem
        |                 WHERE DownloadJobItem.djiDjUid = (SELECT uid FROM MostRecentDlUid)) AS totalSize  
        |    
        """.trimMargin()
    return createFlow(__db, false, arrayOf("DownloadJob", "DownloadJobItem")) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, pubManifestHash)
        val _columnIndexOfStatus: Int = 0
        val _columnIndexOfTransferred: Int = 1
        val _columnIndexOfTotalSize: Int = 2
        val _result: PublicationPinState
        if (_stmt.step()) {
          val _tmpStatus: PublicationPinState.Status
          val _tmp: Int
          _tmp = _stmt.getLong(_columnIndexOfStatus).toInt()
          _tmpStatus = __dbTypeConverters.toPublicationPinStateStatus(_tmp)
          val _tmpTransferred: Long
          _tmpTransferred = _stmt.getLong(_columnIndexOfTransferred)
          val _tmpTotalSize: Long
          _tmpTotalSize = _stmt.getLong(_columnIndexOfTotalSize)
          _result = PublicationPinState(_tmpStatus,_tmpTotalSize,_tmpTransferred)
        } else {
          error("The query result was empty, but expected a single row to return a NON-NULL object of type 'com.ustadmobile.libcache.PublicationPinState'.")
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun updateTransferredProgress(jobItemUid: Int, transferred: Long) {
    val _sql: String = """
        |
        |        UPDATE DownloadJobItem
        |           SET djiTransferred = ?
        |         WHERE djiUid = ?
        |    
        """.trimMargin()
    return performSuspending(__db, false, true) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, transferred)
        _argIndex = 2
        _stmt.bindLong(_argIndex, jobItemUid.toLong())
        _stmt.step()
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun updateStatus(jobItemUid: Int, status: Int) {
    val _sql: String = """
        |
        |        UPDATE DownloadJobItem
        |           SET djiStatus = ?
        |         WHERE djiUid = ?  
        |    
        """.trimMargin()
    return performSuspending(__db, false, true) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, status.toLong())
        _argIndex = 2
        _stmt.bindLong(_argIndex, jobItemUid.toLong())
        _stmt.step()
      } finally {
        _stmt.close()
      }
    }
  }

  public companion object {
    public fun getRequiredConverters(): List<KClass<*>> = emptyList()
  }
}
