package com.ustadmobile.libcache.db.dao

import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.EntityInsertionAdapter
import com.ustadmobile.door.PreparedStatementConfig
import com.ustadmobile.door.ext.prepareAndUseStatement
import com.ustadmobile.door.jdbc.PreparedStatement
import com.ustadmobile.door.jdbc.ext.getStringNonNull
import com.ustadmobile.door.jdbc.ext.mapRows
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.libcache.db.entities.RequestedEntry
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Int
import kotlin.String
import kotlin.collections.List

public class RequestedEntryDao_JdbcImpl(
  public val _db: RoomDatabase,
) : RequestedEntryDao() {
  public val _insertAdapterRequestedEntry_abort: EntityInsertionAdapter<RequestedEntry> = object :
      EntityInsertionAdapter<RequestedEntry>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO RequestedEntry (id, requestSha256, requestedKey, batchId) VALUES(?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO RequestedEntry (id, requestSha256, requestedKey, batchId) VALUES(COALESCE(?,nextval('RequestedEntry_id_seq')), ?, ?, ?)" + if(returnsId) { " RETURNING id" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: RequestedEntry) {
      if(entity.id == 0) {
        stmt.setObject(1, null)
      } else {
        stmt.setInt(1, entity.id)
      }
      stmt.setString(2, entity.requestSha256)
      stmt.setString(3, entity.requestedKey)
      stmt.setInt(4, entity.batchId)
    }
  }

  override fun insertList(requestedSha256s: List<RequestedEntry>) {
    _insertAdapterRequestedEntry_abort.insertList(requestedSha256s)
  }

  override suspend fun insertListAsync(requestedSha256s: List<RequestedEntry>) {
    _insertAdapterRequestedEntry_abort.insertListAsync(requestedSha256s)
  }

  override fun findKeysNotPresent(batchId: Int): List<String> =
      _db.prepareAndUseStatement(PreparedStatementConfig(
    sql = """
    |
    |        SELECT RequestedEntry.requestedKey
    |          FROM RequestedEntry
    |         WHERE RequestedEntry.batchId = ? 
    |           AND NOT EXISTS(
    |               SELECT CacheEntry.key
    |                 FROM CacheEntry
    |                WHERE CacheEntry.key = RequestedEntry.requestedKey
    |           )
    |        
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setInt(1,batchId)
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapRows {
        _result.getStringNonNull(1)
      }
    }
  }

  override fun deleteBatch(batchId: Int) {
    _db.prepareAndUseStatement(PreparedStatementConfig(
      sql = """
      |
      |        DELETE FROM RequestedEntry
      |         WHERE RequestedEntry.batchId = ?    
      |    
      """.trimMargin(),
      readOnly = false,)
    ) { _stmt -> 
      _stmt.setInt(1,batchId)
      _stmt.executeUpdate()
    }
  }
}
