package com.ustadmobile.core.db.dao.xapi

import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.EntityInsertionAdapter
import com.ustadmobile.door.PreparedStatementConfig
import com.ustadmobile.door.ext.prepareAndUseStatementAsync
import com.ustadmobile.door.jdbc.PreparedStatement
import com.ustadmobile.door.jdbc.ext.executeQueryAsyncKmp
import com.ustadmobile.door.jdbc.ext.mapRows
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.entities.xapi.StatementEntityJson
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Long
import kotlin.String
import kotlin.collections.List

public class StatementEntityJsonDao_JdbcImpl(
  public val _db: RoomDatabase,
) : StatementEntityJsonDao() {
  public val _insertAdapterStatementEntityJson_ignore: EntityInsertionAdapter<StatementEntityJson> =
      object : EntityInsertionAdapter<StatementEntityJson>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT  OR IGNORE INTO StatementEntityJson (stmtJsonIdHi, stmtJsonIdLo, stmtEtag, fullStatement) VALUES(?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO StatementEntityJson (stmtJsonIdHi, stmtJsonIdLo, stmtEtag, fullStatement) VALUES(?, ?, ?, ?) ON CONFLICT (stmtJsonIdHi, stmtJsonIdLo) DO NOTHING" + if(returnsId) { " RETURNING stmtJsonIdHi" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: StatementEntityJson) {
      stmt.setLong(1, entity.stmtJsonIdHi)
      stmt.setLong(2, entity.stmtJsonIdLo)
      stmt.setLong(3, entity.stmtEtag)
      stmt.setString(4, entity.fullStatement)
    }
  }

  override suspend fun insertOrIgnoreListAsync(entityList: List<StatementEntityJson>) {
    _insertAdapterStatementEntityJson_ignore.insertListAsync(entityList)
  }

  override suspend fun getStatements(stmtJsonIdHi: Long, stmtJsonIdLo: Long):
      List<StatementEntityJson> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT StatementEntityJson.*
    |          FROM StatementEntityJson
    |         WHERE (    (? = 0 AND ? = 0) 
    |                 OR (stmtJsonIdHi = ? AND stmtJsonIdLo = ?))
    |                  
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,stmtJsonIdHi)
    _stmt.setLong(2,stmtJsonIdLo)
    _stmt.setLong(3,stmtJsonIdHi)
    _stmt.setLong(4,stmtJsonIdLo)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_stmtJsonIdHi = _result.getLong("stmtJsonIdHi")
        val _tmp_stmtJsonIdLo = _result.getLong("stmtJsonIdLo")
        val _tmp_stmtEtag = _result.getLong("stmtEtag")
        val _tmp_fullStatement = _result.getString("fullStatement")
        StatementEntityJson().apply {
          this.stmtJsonIdHi = _tmp_stmtJsonIdHi
          this.stmtJsonIdLo = _tmp_stmtJsonIdLo
          this.stmtEtag = _tmp_stmtEtag
          this.fullStatement = _tmp_fullStatement
        }
      }
    }
  }
}
