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

public class ActivityInteractionDao_JdbcImpl(
  public val _db: RoomDatabase,
) : ActivityInteractionDao() {
  public val _insertAdapterActivityInteractionEntity_ignore:
      EntityInsertionAdapter<ActivityInteractionEntity> = object :
      EntityInsertionAdapter<ActivityInteractionEntity>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT  OR IGNORE INTO ActivityInteractionEntity (aieActivityUid, aieHash, aieProp, aieId, aieLastMod, aieIsDeleted) VALUES(?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO ActivityInteractionEntity (aieActivityUid, aieHash, aieProp, aieId, aieLastMod, aieIsDeleted) VALUES(?, ?, ?, ?, ?, ?) ON CONFLICT (aieActivityUid, aieHash) DO NOTHING" + if(returnsId) { " RETURNING aieActivityUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement,
        entity: ActivityInteractionEntity) {
      stmt.setLong(1, entity.aieActivityUid)
      stmt.setLong(2, entity.aieHash)
      stmt.setInt(3, entity.aieProp)
      stmt.setString(4, entity.aieId)
      stmt.setLong(5, entity.aieLastMod)
      stmt.setBoolean(6, entity.aieIsDeleted)
    }
  }

  override suspend fun insertOrIgnoreAsync(entities: List<ActivityInteractionEntity>) {
    _insertAdapterActivityInteractionEntity_ignore.insertListAsync(entities)
  }

  override suspend fun findActivityUidsWithInteractionEntitiesAsync(activityUids: List<Long>):
      List<Long> = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT DISTINCT ActivityInteractionEntity.aieActivityUid
    |          FROM ActivityInteractionEntity
    |         WHERE ActivityInteractionEntity.aieActivityUid IN (?)
    |    
    """.trimMargin(),
    hasListParams = true,
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setArray(1, _stmt.getConnection().createArrayOrProxyArrayOf("BIGINT",
        activityUids.toTypedArray()))
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        _result.getLong(1)
      }
    }
  }

  override suspend fun findAllByActivityUidAsync(activityUid: Long): List<ActivityInteractionEntity>
      = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT ActivityInteractionEntity.*
    |          FROM ActivityInteractionEntity
    |         WHERE ActivityInteractionEntity.aieActivityUid = ? 
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,activityUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_aieActivityUid = _result.getLong("aieActivityUid")
        val _tmp_aieHash = _result.getLong("aieHash")
        val _tmp_aieProp = _result.getInt("aieProp")
        val _tmp_aieId = _result.getString("aieId")
        val _tmp_aieLastMod = _result.getLong("aieLastMod")
        val _tmp_aieIsDeleted = _result.getBoolean("aieIsDeleted")
        ActivityInteractionEntity().apply {
          this.aieActivityUid = _tmp_aieActivityUid
          this.aieHash = _tmp_aieHash
          this.aieProp = _tmp_aieProp
          this.aieId = _tmp_aieId
          this.aieLastMod = _tmp_aieLastMod
          this.aieIsDeleted = _tmp_aieIsDeleted
        }
      }
    }
  }
}
