package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.door.DoorDatabaseRepository
import com.ustadmobile.door.ext.doorNodeIdHeader
import com.ustadmobile.door.ext.pagingSourceLoadParameters
import com.ustadmobile.door.ext.setRepoUrl
import com.ustadmobile.door.http.RepoDaoFlowHelper
import com.ustadmobile.door.http.RepositoryDaoWithFlowHelper
import com.ustadmobile.door.http.replicateHttpRequestCatchAndLog
import com.ustadmobile.door.http.replicateHttpRequestOrThrow
import com.ustadmobile.door.paging.DoorRepositoryReplicatePullPagingSource
import com.ustadmobile.door.paging.endOfPaginationReached
import com.ustadmobile.door.replication.onClientRepoDoorMessageHttpResponse
import com.ustadmobile.door.replication.withRepoChangeMonitorAsync
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.composites.AssignmentPermissionAndActiveUserSubmitterUid
import com.ustadmobile.lib.db.composites.CoursePermissionAndEnrolment
import com.ustadmobile.lib.db.composites.CoursePermissionAndListDetail
import com.ustadmobile.lib.db.composites.PermissionPair
import com.ustadmobile.lib.db.composites.PermissionTriple
import com.ustadmobile.lib.db.entities.CoursePermission
import io.ktor.client.HttpClient
import io.ktor.client.request.`get`
import io.ktor.client.request.`header`
import io.ktor.client.request.parameter
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Suppress
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer

@Suppress("REDUNDANT_PROJECTION", "LocalVariableName", "ClassName")
public class CoursePermissionDao_Repo(
  public val _db: RoomDatabase,
  public val _repo: DoorDatabaseRepository,
  public val _dao: CoursePermissionDao,
  public val _httpClient: HttpClient,
  public val _clientId: Long,
  public val _endpoint: String,
) : CoursePermissionDao(), RepositoryDaoWithFlowHelper {
  override val repoDaoFlowHelper: RepoDaoFlowHelper = RepoDaoFlowHelper(_repo)


  override fun findByClazzUidAsPagingSource(clazzUid: Long, includeDeleted: Boolean):
      PagingSource<Int, CoursePermissionAndListDetail> = DoorRepositoryReplicatePullPagingSource(
    repo = _repo,
    repoPath = "CoursePermissionDao/findByClazzUidAsPagingSource",
    dbPagingSource = _dao.findByClazzUidAsPagingSource(clazzUid, includeDeleted),
    onLoadHttp =  {
      _pagingParams -> 
      _repo.replicateHttpRequestOrThrow(repoPath =
          "CoursePermissionDao/findByClazzUidAsPagingSource") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/findByClazzUidAsPagingSource")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
          parameter("includeDeleted", _repo.config.json.encodeToString(Boolean.serializer(),
              includeDeleted))
          pagingSourceLoadParameters(
            json = _repo.config.json, 
            keySerializer = Int.serializer().nullable,
            loadParams = _pagingParams
          )
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
        _response.endOfPaginationReached()
      }
    },
  )

  override suspend fun findByUidAndClazzUid(uid: Long, clazzUid: Long): CoursePermission? {
    _repo.replicateHttpRequestCatchAndLog(repoPath = "CoursePermissionDao/findByUidAndClazzUid") {
      val _response = _httpClient.`get` {
        setRepoUrl(_repo.config, "CoursePermissionDao/findByUidAndClazzUid")
        doorNodeIdHeader(_repo)
        `header`("cache-control", "no-store")
        parameter("uid", _repo.config.json.encodeToString(Long.serializer(), uid))
        parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
      }

      _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
    }
    val _result = _dao.findByUidAndClazzUid(uid, clazzUid)
    return _result
  }

  override fun findByUidAndClazzUidAsFlow(uid: Long, clazzUid: Long): Flow<CoursePermission?> =
      repoDaoFlowHelper.asRepoFlow(
    dbFlow = _dao.findByUidAndClazzUidAsFlow(uid, clazzUid),
    onMakeHttpRequest =  {
      _repo.replicateHttpRequestCatchAndLog(repoPath =
          "CoursePermissionDao/findByUidAndClazzUidAsFlow") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/findByUidAndClazzUidAsFlow")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("uid", _repo.config.json.encodeToString(Long.serializer(), uid))
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
      }
    },
  )

  override suspend fun upsertAsync(coursePermission: CoursePermission) {
    _repo.withRepoChangeMonitorAsync("CoursePermission") {
      _dao.upsertAsync(coursePermission)
    }
  }

  override suspend fun setDeleted(
    cpUid: Long,
    isDeleted: Boolean,
    updateTime: Long,
  ) {
    _repo.withRepoChangeMonitorAsync("CoursePermission") {
      _dao.setDeleted(cpUid, isDeleted, updateTime)
    }
  }

  override suspend fun personHasPermissionWithClazzByEnrolmentUidEntities2(accountPersonUid: Long,
      clazzEnrolmentUid: Long): List<CoursePermissionAndEnrolment> {
    val _result = _dao.personHasPermissionWithClazzByEnrolmentUidEntities2(accountPersonUid,
        clazzEnrolmentUid)
    return _result
  }

  override suspend fun userHasEnrolmentEditPermission(accountPersonUid: Long,
      clazzEnrolmentUid: Long): Boolean {
    _repo.replicateHttpRequestCatchAndLog(repoPath =
        "CoursePermissionDao/userHasEnrolmentEditPermission") {
      val _response = _httpClient.`get` {
        setRepoUrl(_repo.config, "CoursePermissionDao/userHasEnrolmentEditPermission")
        doorNodeIdHeader(_repo)
        `header`("cache-control", "no-store")
        parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
            accountPersonUid))
        parameter("clazzEnrolmentUid", _repo.config.json.encodeToString(Long.serializer(),
            clazzEnrolmentUid))
      }

      _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
    }
    val _result = _dao.userHasEnrolmentEditPermission(accountPersonUid, clazzEnrolmentUid)
    return _result
  }

  override suspend fun personHasPermissionWithClazzEntities2(accountPersonUid: Long,
      clazzUid: Long): List<CoursePermissionAndEnrolment> {
    val _result = _dao.personHasPermissionWithClazzEntities2(accountPersonUid, clazzUid)
    return _result
  }

  override fun personHasPermissionWithClazzAsFlow2(
    accountPersonUid: Long,
    clazzUid: Long,
    permission: Long,
  ): Flow<Boolean> = repoDaoFlowHelper.asRepoFlow(
    dbFlow = _dao.personHasPermissionWithClazzAsFlow2(accountPersonUid, clazzUid, permission),
    onMakeHttpRequest =  {
      _repo.replicateHttpRequestCatchAndLog(repoPath =
          "CoursePermissionDao/personHasPermissionWithClazzAsFlow2") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/personHasPermissionWithClazzAsFlow2")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
              accountPersonUid))
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
          parameter("permission", _repo.config.json.encodeToString(Long.serializer(), permission))
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
      }
    },
  )

  override fun personHasPermissionWithClazzPairAsFlow(
    accountPersonUid: Long,
    clazzUid: Long,
    firstPermission: Long,
    secondPermission: Long,
  ): Flow<PermissionPair> = repoDaoFlowHelper.asRepoFlow(
    dbFlow = _dao.personHasPermissionWithClazzPairAsFlow(accountPersonUid, clazzUid,
        firstPermission, secondPermission),
    onMakeHttpRequest =  {
      _repo.replicateHttpRequestCatchAndLog(repoPath =
          "CoursePermissionDao/personHasPermissionWithClazzPairAsFlow") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/personHasPermissionWithClazzPairAsFlow")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
              accountPersonUid))
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
          parameter("firstPermission", _repo.config.json.encodeToString(Long.serializer(),
              firstPermission))
          parameter("secondPermission", _repo.config.json.encodeToString(Long.serializer(),
              secondPermission))
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
      }
    },
  )

  override suspend fun personHasPermissionWithClazzPairAsync(
    accountPersonUid: Long,
    clazzUid: Long,
    firstPermission: Long,
    secondPermission: Long,
  ): PermissionPair {
    _repo.replicateHttpRequestCatchAndLog(repoPath =
        "CoursePermissionDao/personHasPermissionWithClazzPairAsync") {
      val _response = _httpClient.`get` {
        setRepoUrl(_repo.config, "CoursePermissionDao/personHasPermissionWithClazzPairAsync")
        doorNodeIdHeader(_repo)
        `header`("cache-control", "no-store")
        parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
            accountPersonUid))
        parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
        parameter("firstPermission", _repo.config.json.encodeToString(Long.serializer(),
            firstPermission))
        parameter("secondPermission", _repo.config.json.encodeToString(Long.serializer(),
            secondPermission))
      }

      _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
    }
    val _result = _dao.personHasPermissionWithClazzPairAsync(accountPersonUid, clazzUid,
        firstPermission, secondPermission)
    return _result
  }

  override fun personHasPermissionWithClazzTripleAsFlow(
    accountPersonUid: Long,
    clazzUid: Long,
    firstPermission: Long,
    secondPermission: Long,
    thirdPermission: Long,
  ): Flow<PermissionTriple> = repoDaoFlowHelper.asRepoFlow(
    dbFlow = _dao.personHasPermissionWithClazzTripleAsFlow(accountPersonUid, clazzUid,
        firstPermission, secondPermission, thirdPermission),
    onMakeHttpRequest =  {
      _repo.replicateHttpRequestCatchAndLog(repoPath =
          "CoursePermissionDao/personHasPermissionWithClazzTripleAsFlow") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/personHasPermissionWithClazzTripleAsFlow")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
              accountPersonUid))
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
          parameter("firstPermission", _repo.config.json.encodeToString(Long.serializer(),
              firstPermission))
          parameter("secondPermission", _repo.config.json.encodeToString(Long.serializer(),
              secondPermission))
          parameter("thirdPermission", _repo.config.json.encodeToString(Long.serializer(),
              thirdPermission))
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
      }
    },
  )

  override suspend fun personHasPermissionWithClazzAsync2(
    accountPersonUid: Long,
    clazzUid: Long,
    permission: Long,
  ): Boolean {
    _repo.replicateHttpRequestCatchAndLog(repoPath =
        "CoursePermissionDao/personHasPermissionWithClazzAsync2") {
      val _response = _httpClient.`get` {
        setRepoUrl(_repo.config, "CoursePermissionDao/personHasPermissionWithClazzAsync2")
        doorNodeIdHeader(_repo)
        `header`("cache-control", "no-store")
        parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
            accountPersonUid))
        parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
        parameter("permission", _repo.config.json.encodeToString(Long.serializer(), permission))
      }

      _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
    }
    val _result = _dao.personHasPermissionWithClazzAsync2(accountPersonUid, clazzUid, permission)
    return _result
  }

  override suspend
      fun findApplicableCoursePermissionEntitiesForAccountPerson(accountPersonUid: Long):
      List<CoursePermission> {
    val _result = _dao.findApplicableCoursePermissionEntitiesForAccountPerson(accountPersonUid)
    return _result
  }

  override fun userPermissionsForAssignmentSubmitterUid(
    accountPersonUid: Long,
    assignmentUid: Long,
    clazzUid: Long,
    submitterUid: Long,
  ): Flow<AssignmentPermissionAndActiveUserSubmitterUid> = repoDaoFlowHelper.asRepoFlow(
    dbFlow = _dao.userPermissionsForAssignmentSubmitterUid(accountPersonUid, assignmentUid,
        clazzUid, submitterUid),
    onMakeHttpRequest =  {
      _repo.replicateHttpRequestCatchAndLog(repoPath =
          "CoursePermissionDao/userPermissionsForAssignmentSubmitterUid") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "CoursePermissionDao/userPermissionsForAssignmentSubmitterUid")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          parameter("accountPersonUid", _repo.config.json.encodeToString(Long.serializer(),
              accountPersonUid))
          parameter("assignmentUid", _repo.config.json.encodeToString(Long.serializer(),
              assignmentUid))
          parameter("clazzUid", _repo.config.json.encodeToString(Long.serializer(), clazzUid))
          parameter("submitterUid", _repo.config.json.encodeToString(Long.serializer(),
              submitterUid))
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
      }
    },
  )
}
