package com.ustadmobile.libcache.db.dao

import androidx.room.EntityInsertAdapter
import androidx.room.RoomDatabase
import androidx.room.coroutines.createFlow
import androidx.room.util.appendPlaceholders
import androidx.room.util.getColumnIndexOrThrow
import androidx.room.util.performSuspending
import androidx.sqlite.SQLiteStatement
import com.ustadmobile.libcache.db.composites.NeighborCacheEntryAndNeighborCache
import com.ustadmobile.libcache.db.entities.NeighborCache
import com.ustadmobile.libcache.db.entities.NeighborCacheEntry
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 kotlin.text.StringBuilder
import kotlinx.coroutines.flow.Flow

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

  private val __insertAdapterOfNeighborCacheEntry: EntityInsertAdapter<NeighborCacheEntry>
  init {
    this.__db = __db
    this.__insertAdapterOfNeighborCacheEntry = object : EntityInsertAdapter<NeighborCacheEntry>() {
      protected override fun createQuery(): String = "INSERT OR REPLACE INTO `NeighborCacheEntry` (`nceNeighborUid`,`nceUrlHash`) VALUES (?,?)"

      protected override fun bind(statement: SQLiteStatement, entity: NeighborCacheEntry) {
        statement.bindLong(1, entity.nceNeighborUid)
        statement.bindLong(2, entity.nceUrlHash)
      }
    }
  }

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

  public override fun allEntriesAsFlow(): Flow<List<NeighborCacheEntry>> {
    val _sql: String = """
        |
        |        SELECT NeighborCacheEntry.* 
        |          FROM NeighborCacheEntry
        |    
        """.trimMargin()
    return createFlow(__db, false, arrayOf("NeighborCacheEntry")) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        val _columnIndexOfNceNeighborUid: Int = getColumnIndexOrThrow(_stmt, "nceNeighborUid")
        val _columnIndexOfNceUrlHash: Int = getColumnIndexOrThrow(_stmt, "nceUrlHash")
        val _result: MutableList<NeighborCacheEntry> = mutableListOf()
        while (_stmt.step()) {
          val _item: NeighborCacheEntry
          val _tmpNceNeighborUid: Long
          _tmpNceNeighborUid = _stmt.getLong(_columnIndexOfNceNeighborUid)
          val _tmpNceUrlHash: Long
          _tmpNceUrlHash = _stmt.getLong(_columnIndexOfNceUrlHash)
          _item = NeighborCacheEntry(_tmpNceNeighborUid,_tmpNceUrlHash)
          _result.add(_item)
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun findAvailableEntries(urlHashes: List<Long>): List<Long> {
    val _stringBuilder: StringBuilder = StringBuilder()
    _stringBuilder.append("""
        |
        |""".trimMargin())
    _stringBuilder.append("        SELECT NeighborCacheEntry.nceUrlHash")
    _stringBuilder.append("""
        |
        |""".trimMargin())
    _stringBuilder.append("          FROM NeighborCacheEntry")
    _stringBuilder.append("""
        |
        |""".trimMargin())
    _stringBuilder.append("         WHERE NeighborCacheEntry.nceUrlHash IN (")
    val _inputSize: Int = urlHashes.size
    appendPlaceholders(_stringBuilder, _inputSize)
    _stringBuilder.append(") ")
    _stringBuilder.append("""
        |
        |""".trimMargin())
    _stringBuilder.append("    ")
    val _sql: String = _stringBuilder.toString()
    return performSuspending(__db, true, false) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        for (_item: Long in urlHashes) {
          _stmt.bindLong(_argIndex, _item)
          _argIndex++
        }
        val _result: MutableList<Long> = mutableListOf()
        while (_stmt.step()) {
          val _item_1: Long
          _item_1 = _stmt.getLong(0)
          _result.add(_item_1)
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

  public override suspend fun findAvailableNeighborsByUrlHash(urlHash: Long): List<NeighborCacheEntryAndNeighborCache> {
    val _sql: String = """
        |
        |        SELECT NeighborCacheEntry.*,
        |               NeighborCache.*
        |          FROM NeighborCacheEntry
        |               JOIN NeighborCache
        |                    ON NeighborCache.neighborUid = NeighborCacheEntry.nceNeighborUid
        |         WHERE NeighborCacheEntry.nceUrlHash = ?
        |           AND NeighborCache.neighborStatus = 1
        |    
        """.trimMargin()
    return performSuspending(__db, true, false) { _connection ->
      val _stmt: SQLiteStatement = _connection.prepare(_sql)
      try {
        var _argIndex: Int = 1
        _stmt.bindLong(_argIndex, urlHash)
        val _columnIndexOfNceNeighborUid: Int = getColumnIndexOrThrow(_stmt, "nceNeighborUid")
        val _columnIndexOfNceUrlHash: Int = getColumnIndexOrThrow(_stmt, "nceUrlHash")
        val _columnIndexOfNeighborUid: Int = getColumnIndexOrThrow(_stmt, "neighborUid")
        val _columnIndexOfNeighborDeviceName: Int = getColumnIndexOrThrow(_stmt, "neighborDeviceName")
        val _columnIndexOfNeighborIp: Int = getColumnIndexOrThrow(_stmt, "neighborIp")
        val _columnIndexOfNeighborUdpPort: Int = getColumnIndexOrThrow(_stmt, "neighborUdpPort")
        val _columnIndexOfNeighborHttpPort: Int = getColumnIndexOrThrow(_stmt, "neighborHttpPort")
        val _columnIndexOfNeighborDiscovered: Int = getColumnIndexOrThrow(_stmt, "neighborDiscovered")
        val _columnIndexOfNeighborPingTime: Int = getColumnIndexOrThrow(_stmt, "neighborPingTime")
        val _columnIndexOfNeighborLastSeen: Int = getColumnIndexOrThrow(_stmt, "neighborLastSeen")
        val _columnIndexOfNeighborStatus: Int = getColumnIndexOrThrow(_stmt, "neighborStatus")
        val _result: MutableList<NeighborCacheEntryAndNeighborCache> = mutableListOf()
        while (_stmt.step()) {
          val _item: NeighborCacheEntryAndNeighborCache
          val _tmpNeighborCacheEntry: NeighborCacheEntry
          val _tmpNceNeighborUid: Long
          _tmpNceNeighborUid = _stmt.getLong(_columnIndexOfNceNeighborUid)
          val _tmpNceUrlHash: Long
          _tmpNceUrlHash = _stmt.getLong(_columnIndexOfNceUrlHash)
          _tmpNeighborCacheEntry = NeighborCacheEntry(_tmpNceNeighborUid,_tmpNceUrlHash)
          val _tmpNeighborCache: NeighborCache
          val _tmpNeighborUid: Long
          _tmpNeighborUid = _stmt.getLong(_columnIndexOfNeighborUid)
          val _tmpNeighborDeviceName: String
          _tmpNeighborDeviceName = _stmt.getText(_columnIndexOfNeighborDeviceName)
          val _tmpNeighborIp: String
          _tmpNeighborIp = _stmt.getText(_columnIndexOfNeighborIp)
          val _tmpNeighborUdpPort: Int
          _tmpNeighborUdpPort = _stmt.getLong(_columnIndexOfNeighborUdpPort).toInt()
          val _tmpNeighborHttpPort: Int
          _tmpNeighborHttpPort = _stmt.getLong(_columnIndexOfNeighborHttpPort).toInt()
          val _tmpNeighborDiscovered: Long
          _tmpNeighborDiscovered = _stmt.getLong(_columnIndexOfNeighborDiscovered)
          val _tmpNeighborPingTime: Int
          _tmpNeighborPingTime = _stmt.getLong(_columnIndexOfNeighborPingTime).toInt()
          val _tmpNeighborLastSeen: Long
          _tmpNeighborLastSeen = _stmt.getLong(_columnIndexOfNeighborLastSeen)
          val _tmpNeighborStatus: Int
          _tmpNeighborStatus = _stmt.getLong(_columnIndexOfNeighborStatus).toInt()
          _tmpNeighborCache = NeighborCache(_tmpNeighborUid,_tmpNeighborDeviceName,_tmpNeighborIp,_tmpNeighborUdpPort,_tmpNeighborHttpPort,_tmpNeighborDiscovered,_tmpNeighborPingTime,_tmpNeighborLastSeen,_tmpNeighborStatus)
          _item = NeighborCacheEntryAndNeighborCache(_tmpNeighborCache,_tmpNeighborCacheEntry)
          _result.add(_item)
        }
        _result
      } finally {
        _stmt.close()
      }
    }
  }

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