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

public class ContentCategoryDao_JdbcImpl(
  public val _db: RoomDatabase,
) : ContentCategoryDao() {
  public val _insertAdapterContentCategory_abort: EntityInsertionAdapter<ContentCategory> = object :
      EntityInsertionAdapter<ContentCategory>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO ContentCategory (contentCategoryUid, ctnCatContentCategorySchemaUid, name, contentCategoryLocalChangeSeqNum, contentCategoryMasterChangeSeqNum, contentCategoryLastChangedBy, contentCategoryLct) VALUES(?, ?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO ContentCategory (contentCategoryUid, ctnCatContentCategorySchemaUid, name, contentCategoryLocalChangeSeqNum, contentCategoryMasterChangeSeqNum, contentCategoryLastChangedBy, contentCategoryLct) VALUES(COALESCE(?,nextval('ContentCategory_contentCategoryUid_seq')), ?, ?, ?, ?, ?, ?)" + if(returnsId) { " RETURNING contentCategoryUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: ContentCategory) {
      if(entity.contentCategoryUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.contentCategoryUid)
      }
      stmt.setLong(2, entity.ctnCatContentCategorySchemaUid)
      stmt.setString(3, entity.name)
      stmt.setLong(4, entity.contentCategoryLocalChangeSeqNum)
      stmt.setLong(5, entity.contentCategoryMasterChangeSeqNum)
      stmt.setInt(6, entity.contentCategoryLastChangedBy)
      stmt.setLong(7, entity.contentCategoryLct)
    }
  }

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

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

  public override fun insertList(entityList: List<ContentCategory>) {
    _insertAdapterContentCategory_abort.insertList(entityList)
  }

  public override fun update(entity: ContentCategory) {
    val _sql =
        "UPDATE ContentCategory SET ctnCatContentCategorySchemaUid = ?, name = ?, contentCategoryLocalChangeSeqNum = ?, contentCategoryMasterChangeSeqNum = ?, contentCategoryLastChangedBy = ?, contentCategoryLct = ? WHERE contentCategoryUid = ?"
    _db.prepareAndUseStatement(_sql) {
       _stmt ->
      _stmt.setLong(1, entity.ctnCatContentCategorySchemaUid)
      _stmt.setString(2, entity.name)
      _stmt.setLong(3, entity.contentCategoryLocalChangeSeqNum)
      _stmt.setLong(4, entity.contentCategoryMasterChangeSeqNum)
      _stmt.setInt(5, entity.contentCategoryLastChangedBy)
      _stmt.setLong(6, entity.contentCategoryLct)
      _stmt.setLong(7, entity.contentCategoryUid)
      _stmt.executeUpdate()
    }
  }

  override fun publicContentCategories(): List<ContentCategory> =
      _db.prepareAndUseStatement(PreparedStatementConfig(
    sql = "SELECT ContentCategory.* FROM ContentCategory",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapRows {
        val _tmp_contentCategoryUid = _result.getLong("contentCategoryUid")
        val _tmp_ctnCatContentCategorySchemaUid = _result.getLong("ctnCatContentCategorySchemaUid")
        val _tmp_name = _result.getString("name")
        val _tmp_contentCategoryLocalChangeSeqNum =
            _result.getLong("contentCategoryLocalChangeSeqNum")
        val _tmp_contentCategoryMasterChangeSeqNum =
            _result.getLong("contentCategoryMasterChangeSeqNum")
        val _tmp_contentCategoryLastChangedBy = _result.getInt("contentCategoryLastChangedBy")
        val _tmp_contentCategoryLct = _result.getLong("contentCategoryLct")
        ContentCategory().apply {
          this.contentCategoryUid = _tmp_contentCategoryUid
          this.ctnCatContentCategorySchemaUid = _tmp_ctnCatContentCategorySchemaUid
          this.name = _tmp_name
          this.contentCategoryLocalChangeSeqNum = _tmp_contentCategoryLocalChangeSeqNum
          this.contentCategoryMasterChangeSeqNum = _tmp_contentCategoryMasterChangeSeqNum
          this.contentCategoryLastChangedBy = _tmp_contentCategoryLastChangedBy
          this.contentCategoryLct = _tmp_contentCategoryLct
        }
      }
    }
  }

  override fun findCategoryBySchemaIdAndName(schemaId: Long, name: String): ContentCategory? =
      _db.prepareAndUseStatement(PreparedStatementConfig(
    sql = "SELECT * FROM ContentCategory WHERE ctnCatContentCategorySchemaUid = ? AND name = ?",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,schemaId)
    _stmt.setString(2,name)
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_contentCategoryUid = _result.getLong("contentCategoryUid")
        val _tmp_ctnCatContentCategorySchemaUid = _result.getLong("ctnCatContentCategorySchemaUid")
        val _tmp_name = _result.getString("name")
        val _tmp_contentCategoryLocalChangeSeqNum =
            _result.getLong("contentCategoryLocalChangeSeqNum")
        val _tmp_contentCategoryMasterChangeSeqNum =
            _result.getLong("contentCategoryMasterChangeSeqNum")
        val _tmp_contentCategoryLastChangedBy = _result.getInt("contentCategoryLastChangedBy")
        val _tmp_contentCategoryLct = _result.getLong("contentCategoryLct")
        ContentCategory().apply {
          this.contentCategoryUid = _tmp_contentCategoryUid
          this.ctnCatContentCategorySchemaUid = _tmp_ctnCatContentCategorySchemaUid
          this.name = _tmp_name
          this.contentCategoryLocalChangeSeqNum = _tmp_contentCategoryLocalChangeSeqNum
          this.contentCategoryMasterChangeSeqNum = _tmp_contentCategoryMasterChangeSeqNum
          this.contentCategoryLastChangedBy = _tmp_contentCategoryLastChangedBy
          this.contentCategoryLct = _tmp_contentCategoryLct
        }
      }
    }
  }
}
