package com.ustadmobile.core.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.mapNextRow
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.entities.LanguageVariant
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Long
import kotlin.String
import kotlin.collections.List

public class LanguageVariantDao_JdbcImpl(
  public val _db: RoomDatabase,
) : LanguageVariantDao() {
  public val _insertAdapterLanguageVariant_abort: EntityInsertionAdapter<LanguageVariant> = object :
      EntityInsertionAdapter<LanguageVariant>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO LanguageVariant (langVariantUid, langUid, countryCode, name, langVariantLocalChangeSeqNum, langVariantMasterChangeSeqNum, langVariantLastChangedBy, langVariantLct) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO LanguageVariant (langVariantUid, langUid, countryCode, name, langVariantLocalChangeSeqNum, langVariantMasterChangeSeqNum, langVariantLastChangedBy, langVariantLct) VALUES(COALESCE(?,nextval('LanguageVariant_langVariantUid_seq')), ?, ?, ?, ?, ?, ?, ?)" + if(returnsId) { " RETURNING langVariantUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: LanguageVariant) {
      if(entity.langVariantUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.langVariantUid)
      }
      stmt.setLong(2, entity.langUid)
      stmt.setString(3, entity.countryCode)
      stmt.setString(4, entity.name)
      stmt.setLong(5, entity.langVariantLocalChangeSeqNum)
      stmt.setLong(6, entity.langVariantMasterChangeSeqNum)
      stmt.setInt(7, entity.langVariantLastChangedBy)
      stmt.setLong(8, entity.langVariantLct)
    }
  }

  public override fun insert(entity: LanguageVariant): Long {
    val _retVal = _insertAdapterLanguageVariant_abort.insertAndReturnId(entity)
    return _retVal
  }

  public override suspend fun insertAsync(entity: LanguageVariant): Long {
    val _retVal = _insertAdapterLanguageVariant_abort.insertAndReturnIdAsync(entity)
    return _retVal
  }

  public override fun insertList(entityList: List<LanguageVariant>) {
    _insertAdapterLanguageVariant_abort.insertList(entityList)
  }

  public override fun update(entity: LanguageVariant) {
    val _sql =
        "UPDATE LanguageVariant SET langUid = ?, countryCode = ?, name = ?, langVariantLocalChangeSeqNum = ?, langVariantMasterChangeSeqNum = ?, langVariantLastChangedBy = ?, langVariantLct = ? WHERE langVariantUid = ?"
    _db.prepareAndUseStatement(_sql) {
       _stmt ->
      _stmt.setLong(1, entity.langUid)
      _stmt.setString(2, entity.countryCode)
      _stmt.setString(3, entity.name)
      _stmt.setLong(4, entity.langVariantLocalChangeSeqNum)
      _stmt.setLong(5, entity.langVariantMasterChangeSeqNum)
      _stmt.setInt(6, entity.langVariantLastChangedBy)
      _stmt.setLong(7, entity.langVariantLct)
      _stmt.setLong(8, entity.langVariantUid)
      _stmt.executeUpdate()
    }
  }

  override fun findByCode(countryCode: String): LanguageVariant? =
      _db.prepareAndUseStatement(PreparedStatementConfig(
    sql = "SELECT * FROM LanguageVariant WHERE countryCode = ? LIMIT 1",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setString(1,countryCode)
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_langVariantUid = _result.getLong("langVariantUid")
        val _tmp_langUid = _result.getLong("langUid")
        val _tmp_countryCode = _result.getString("countryCode")
        val _tmp_name = _result.getString("name")
        val _tmp_langVariantLocalChangeSeqNum = _result.getLong("langVariantLocalChangeSeqNum")
        val _tmp_langVariantMasterChangeSeqNum = _result.getLong("langVariantMasterChangeSeqNum")
        val _tmp_langVariantLastChangedBy = _result.getInt("langVariantLastChangedBy")
        val _tmp_langVariantLct = _result.getLong("langVariantLct")
        LanguageVariant().apply {
          this.langVariantUid = _tmp_langVariantUid
          this.langUid = _tmp_langUid
          this.countryCode = _tmp_countryCode
          this.name = _tmp_name
          this.langVariantLocalChangeSeqNum = _tmp_langVariantLocalChangeSeqNum
          this.langVariantMasterChangeSeqNum = _tmp_langVariantMasterChangeSeqNum
          this.langVariantLastChangedBy = _tmp_langVariantLastChangedBy
          this.langVariantLct = _tmp_langVariantLct
        }
      }
    }
  }
}
