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

package at.bitfire.davdroid.resource

import android.content.Context
import android.content.Intent
import android.net.Uri
import at.bitfire.davdroid.resource.LocalResource.Companion.FLAG_REMOTELY_PRESENT
import java.util.Optional

/**
 * This is an interface between the SyncManager and a resource in the local storage.
 *
 * It defines operations that are used by SyncManager for all sync data types.
 */
interface LocalResource {

    companion object {
        /**
         * Resource is present on remote server. This flag is used to identify resources
         * which are not present on the remote server anymore and can be deleted at the end
         * of the synchronization.
         */
        const val FLAG_REMOTELY_PRESENT = 1
    }


    /**
     * Unique ID which identifies the resource in the local storage. May be null if the
     * resource has not been saved yet.
     */
    val id: Long?

    /**
     * Remote file name for the resource, for instance `mycontact.vcf`. Also used to determine whether
     * a dirty record has just been created (in this case, [fileName] is *null*) or modified
     * (in this case, [fileName] is the remote file name).
     */
    val fileName: String?

    /** remote ETag for the resource */
    val eTag: String?

    /** remote Schedule-Tag for the resource */
    val scheduleTag: String?

    /** bitfield of flags; currently either [FLAG_REMOTELY_PRESENT] or 0 */
    val flags: Int

    /**
     * Unsets the _dirty_ field of the resource and updates other sync-related fields in the content provider.
     * Does not affect `this` object itself (which is immutable).
     *
     * @param fileName      If this optional argument is present, [LocalResource.fileName] will be set to its value.
     * @param eTag          ETag of the uploaded resource as returned by the server (null if the server didn't return one)
     * @param scheduleTag   CalDAV only: `Schedule-Tag` of the uploaded resource as returned by the server
     *                      (null if not applicable or if the server didn't return one)
     */
    fun clearDirty(fileName: Optional<String>, eTag: String?, scheduleTag: String? = null)

    /**
     * Sets (local) flags of the resource in the content provider.
     * Does not affect `this` object itself (which is immutable).
     *
     * At the moment, the only allowed values are 0 and [FLAG_REMOTELY_PRESENT].
     */
    fun updateFlags(flags: Int)

    /**
     * Updates the local UID of the resource in the content provider.
     * Usually used to persist a UID that has been created during an upload of a locally created resource.
     */
    fun updateUid(uid: String)

    /**
     * Updates the local SEQUENCE of the resource in the content provider.
     *
     * @throws NotImplementedError  if SEQUENCE update is not supported
     */
    fun updateSequence(sequence: Int)

    /**
     * Deletes the data object from the content provider.
     */
    fun deleteLocal()

    /**
     * Undoes deletion of the data object from the content provider.
     */
    fun resetDeleted()

    /**
     * User-readable debug summary of this local resource (used in debug info)
     */
    fun getDebugSummary(): String

    /**
     * Returns the content provider URI that opens the local resource for viewing ([Intent.ACTION_VIEW])
     * in its respective app.
     *
     * For instance, in case of a local raw contact, this method could return the content provider URI
     * that identifies the corresponding contact.
     *
     * @return content provider URI, or `null` if not available
     */
    fun getViewUri(context: Context): Uri?

}