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.ContentEntryContentCategoryJoin
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Long
import kotlin.String
import kotlin.collections.List

public class ContentEntryContentCategoryJoinDao_JdbcImpl(
  public val _db: RoomDatabase,
) : ContentEntryContentCategoryJoinDao() {
  public val _insertAdapterContentEntryContentCategoryJoin_abort:
      EntityInsertionAdapter<ContentEntryContentCategoryJoin> = object :
      EntityInsertionAdapter<ContentEntryContentCategoryJoin>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO ContentEntryContentCategoryJoin (ceccjUid, ceccjContentEntryUid, ceccjContentCategoryUid, ceccjLocalChangeSeqNum, ceccjMasterChangeSeqNum, ceccjLastChangedBy, ceccjLct) VALUES(?, ?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO ContentEntryContentCategoryJoin (ceccjUid, ceccjContentEntryUid, ceccjContentCategoryUid, ceccjLocalChangeSeqNum, ceccjMasterChangeSeqNum, ceccjLastChangedBy, ceccjLct) VALUES(COALESCE(?,nextval('ContentEntryContentCategoryJoin_ceccjUid_seq')), ?, ?, ?, ?, ?, ?)" + if(returnsId) { " RETURNING ceccjUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement,
        entity: ContentEntryContentCategoryJoin) {
      if(entity.ceccjUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.ceccjUid)
      }
      stmt.setLong(2, entity.ceccjContentEntryUid)
      stmt.setLong(3, entity.ceccjContentCategoryUid)
      stmt.setLong(4, entity.ceccjLocalChangeSeqNum)
      stmt.setLong(5, entity.ceccjMasterChangeSeqNum)
      stmt.setInt(6, entity.ceccjLastChangedBy)
      stmt.setLong(7, entity.ceccjLct)
    }
  }

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

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

  public override fun insertList(entityList: List<ContentEntryContentCategoryJoin>) {
    _insertAdapterContentEntryContentCategoryJoin_abort.insertList(entityList)
  }

  public override fun update(entity: ContentEntryContentCategoryJoin) {
    val _sql =
        "UPDATE ContentEntryContentCategoryJoin SET ceccjContentEntryUid = ?, ceccjContentCategoryUid = ?, ceccjLocalChangeSeqNum = ?, ceccjMasterChangeSeqNum = ?, ceccjLastChangedBy = ?, ceccjLct = ? WHERE ceccjUid = ?"
    _db.prepareAndUseStatement(_sql) {
       _stmt ->
      _stmt.setLong(1, entity.ceccjContentEntryUid)
      _stmt.setLong(2, entity.ceccjContentCategoryUid)
      _stmt.setLong(3, entity.ceccjLocalChangeSeqNum)
      _stmt.setLong(4, entity.ceccjMasterChangeSeqNum)
      _stmt.setInt(5, entity.ceccjLastChangedBy)
      _stmt.setLong(6, entity.ceccjLct)
      _stmt.setLong(7, entity.ceccjUid)
      _stmt.executeUpdate()
    }
  }

  override fun publicContentEntryContentCategoryJoins(): List<ContentEntryContentCategoryJoin> =
      _db.prepareAndUseStatement(PreparedStatementConfig(
    sql =
        "SELECT ContentEntryContentCategoryJoin.* FROM ContentEntryContentCategoryJoin LEFT JOIN ContentEntry ON ContentEntryContentCategoryJoin.ceccjContentEntryUid = ContentEntry.contentEntryUid WHERE ContentEntry.publik",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapRows {
        val _tmp_ceccjUid = _result.getLong("ceccjUid")
        val _tmp_ceccjContentEntryUid = _result.getLong("ceccjContentEntryUid")
        val _tmp_ceccjContentCategoryUid = _result.getLong("ceccjContentCategoryUid")
        val _tmp_ceccjLocalChangeSeqNum = _result.getLong("ceccjLocalChangeSeqNum")
        val _tmp_ceccjMasterChangeSeqNum = _result.getLong("ceccjMasterChangeSeqNum")
        val _tmp_ceccjLastChangedBy = _result.getInt("ceccjLastChangedBy")
        val _tmp_ceccjLct = _result.getLong("ceccjLct")
        ContentEntryContentCategoryJoin().apply {
          this.ceccjUid = _tmp_ceccjUid
          this.ceccjContentEntryUid = _tmp_ceccjContentEntryUid
          this.ceccjContentCategoryUid = _tmp_ceccjContentCategoryUid
          this.ceccjLocalChangeSeqNum = _tmp_ceccjLocalChangeSeqNum
          this.ceccjMasterChangeSeqNum = _tmp_ceccjMasterChangeSeqNum
          this.ceccjLastChangedBy = _tmp_ceccjLastChangedBy
          this.ceccjLct = _tmp_ceccjLct
        }
      }
    }
  }

  override fun findJoinByParentChildUuids(categoryUid: Long, contentEntry: Long):
      ContentEntryContentCategoryJoin? = _db.prepareAndUseStatement(PreparedStatementConfig(
    sql =
        "SELECT * from ContentEntryContentCategoryJoin WHERE ceccjContentCategoryUid = ? AND ceccjContentEntryUid = ?",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,categoryUid)
    _stmt.setLong(2,contentEntry)
    _stmt.executeQuery().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_ceccjUid = _result.getLong("ceccjUid")
        val _tmp_ceccjContentEntryUid = _result.getLong("ceccjContentEntryUid")
        val _tmp_ceccjContentCategoryUid = _result.getLong("ceccjContentCategoryUid")
        val _tmp_ceccjLocalChangeSeqNum = _result.getLong("ceccjLocalChangeSeqNum")
        val _tmp_ceccjMasterChangeSeqNum = _result.getLong("ceccjMasterChangeSeqNum")
        val _tmp_ceccjLastChangedBy = _result.getInt("ceccjLastChangedBy")
        val _tmp_ceccjLct = _result.getLong("ceccjLct")
        ContentEntryContentCategoryJoin().apply {
          this.ceccjUid = _tmp_ceccjUid
          this.ceccjContentEntryUid = _tmp_ceccjContentEntryUid
          this.ceccjContentCategoryUid = _tmp_ceccjContentCategoryUid
          this.ceccjLocalChangeSeqNum = _tmp_ceccjLocalChangeSeqNum
          this.ceccjMasterChangeSeqNum = _tmp_ceccjMasterChangeSeqNum
          this.ceccjLastChangedBy = _tmp_ceccjLastChangedBy
          this.ceccjLct = _tmp_ceccjLct
        }
      }
    }
  }
}
