/*
 * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
 */

package at.bitfire.davdroid.resource

import kotlinx.coroutines.flow.Flow

/**
 * This is an interface between the Syncer/SyncManager and a collection in the local storage.
 *
 * It defines operations that are used during sync for all sync data types.
 */
interface LocalCollection<out T: LocalResource> {

    /** a tag that uniquely identifies the collection (DAVx5-wide) */
    val tag: String

    /** ID of the collection in the database (corresponds to [at.bitfire.davdroid.db.Collection.id]) */
    val dbCollectionId: Long?

    /** collection title (used for user notifications etc.) **/
    val title: String

    var lastSyncState: SyncState?

    /**
     * Whether the collection should be treated as read-only on sync.
     * Stops uploading dirty events (Server side changes are still downloaded).
     */
    val readOnly: Boolean

    /**
     * Finds local resources of this collection which have been marked as *deleted* by the user
     * or an app acting on their behalf.
     *
     * @return [Flow] of resources marked as *deleted*
     */
    fun findDeleted(): Flow<T>

    /**
     * Finds local resources of this collection which have been marked as *dirty*, i.e. resources
     * which have been modified by the user or an app acting on their behalf.
     *
     * @return [Flow] of resources marked as *dirty*
     */
    fun findDirty(): Flow<T>

    /**
     * Finds a local resource of this collection with a given file name. (File names are assigned
     * by the sync adapter.)
     *
     * @param name file name to look for
     * @return resource with the given name, or null if none
     */
    suspend fun findByName(name: String): T?

    /**
     * Updates the flags value for entries which are not dirty.
     *
     * @param flags    value of flags to set (for instance, [LocalResource.FLAG_REMOTELY_PRESENT]])
     *
     * @return         number of marked entries
     */
    fun markNotDirty(flags: Int): Int

    /**
     * Removes entries which are not dirty with a given flag combination.
     *
     * @param flags    exact flags value to remove entries with (for instance, if this is [LocalResource.FLAG_REMOTELY_PRESENT]],
     *                 all entries with exactly this flag will be removed)
     *
     * @return         number of removed entries
     */
    suspend fun removeNotDirtyMarked(flags: Int): Int


    /**
     * Forgets the ETags of all members so that they will be reloaded from the server during sync.
     */
    fun forgetETags()

    /**
     * Counts all resources in this collection.
     *
     * @return total number of resources
     */
    fun countAll(): Int

    /**
     * Counts resources in this collection that are locally deleted (pending removal from server).
     *
     * @return number of deleted resources
     */
    fun countDeleted(): Int

    /**
     * Counts resources in this collection that are locally modified (pending upload to server),
     * excluding resources already marked as deleted.
     *
     * @return number of modified resources
     */
    fun countModified(): Int

    /**
     * Counts resources in this collection that are locally marked as *dirty*.
     *
     * @return number of dirty resources
     */
    fun countDirty(): Int

}