package com.ustadmobile.core.util.ext

import com.ustadmobile.core.db.UmAppDatabase
import com.ustadmobile.door.DoorDatabaseRepository
import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.ext.dbType
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonGroup
import com.ustadmobile.lib.db.entities.PersonGroupMember
import com.ustadmobile.lib.db.entities.ScopedGrant


/**
 * Inserts the person, sets its group and groupmember. Does not check if its an update
 */
@Deprecated("Should use AddNewPersonUseCase instead")
suspend fun <T: Person> UmAppDatabase.insertPersonAndGroup(
    entity: T,
    groupFlag: Int = PersonGroup.PERSONGROUP_FLAG_PERSONGROUP
): T{
    val groupPerson = PersonGroup().apply {
        groupName = "Person individual group"
        personGroupFlag = groupFlag
    }
    //Create person's group
    groupPerson.groupUid = personGroupDao().insertAsync(groupPerson)

    //Assign to person
    entity.personGroupUid = groupPerson.groupUid
    entity.personUid = personDao().insertAsync(entity)

    //Assign person to PersonGroup ie: Create PersonGroupMember
    personGroupMemberDao().insertAsync(
            PersonGroupMember(entity.personUid, entity.personGroupUid))

    //Grant the person all permissions on their own data

    grantScopedPermission(entity, Long.MAX_VALUE, Person.TABLE_ID, entity.personUid)

    return entity
}

/**
 * Gets the maximum number of items that can be in a query parameter of type list. This is 100 on
 * SQLite and unlimited (-1) on Postgres
 */
internal val UmAppDatabase.maxQueryParamListSize: Int
    get() = if(this.dbType() == DoorDbType.SQLITE) 99 else -1


data class ScopedGrantResult(val sgUid: Long)

@Deprecated("This has been replaced with SystemPermission and CoursePermission")
suspend fun UmAppDatabase.grantScopedPermission(toGroupUid: Long, permissions: Long,
                                                scopeTableId: Int, scopeEntityUid: Long) : ScopedGrantResult{
    val sgUid = scopedGrantDao().insertAsync(ScopedGrant().apply {
        sgGroupUid = toGroupUid
        sgPermissions = permissions
        sgTableId = scopeTableId
        sgEntityUid = scopeEntityUid
    })

    return ScopedGrantResult(sgUid)
}

@Deprecated("This has been replaced with SystemPermission and CoursePermission")
suspend fun UmAppDatabase.grantScopedPermission(toPerson: Person, permissions: Long,
                                                scopeTableId: Int, scopeEntityUid: Long): ScopedGrantResult {
    return grantScopedPermission(toPerson.personGroupUid, permissions, scopeTableId, scopeEntityUid)
}

suspend fun <R> UmAppDatabase.localFirstThenRepoIfNull(
    block: suspend (UmAppDatabase) -> R
): R {
    val localDb = (this as? DoorDatabaseRepository)?.db as? UmAppDatabase
    val localResult: R? = localDb?.let { block(it) }
    if(localResult != null)
        return localResult

    return block(this)
}

suspend fun UmAppDatabase.localFirstThenRepoIfFalse(
    block: suspend (UmAppDatabase) -> Boolean
): Boolean {
    val localDb = (this as? DoorDatabaseRepository)?.db as? UmAppDatabase
    val localResult = localDb?.let { block(it) }
    if(localResult == true)
        return localResult

    return block(this)
}
