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

package at.bitfire.davdroid.resource

import android.content.ContentValues
import androidx.core.content.contentValuesOf
import at.bitfire.ical4android.DmfsTask
import at.bitfire.ical4android.DmfsTaskFactory
import at.bitfire.ical4android.DmfsTaskList
import at.bitfire.ical4android.Task
import at.bitfire.synctools.storage.BatchOperation
import org.dmfs.tasks.contract.TaskContract.Tasks
import java.util.Optional
import java.util.UUID

class LocalTask: DmfsTask, LocalResource<Task> {

    companion object {
        const val COLUMN_ETAG = Tasks.SYNC1
        const val COLUMN_FLAGS = Tasks.SYNC2
    }

    override var fileName: String? = null

    override var scheduleTag: String? = null
    override var eTag: String? = null

    override var flags = 0
        private set


    constructor(taskList: DmfsTaskList<*>, task: Task, fileName: String?, eTag: String?, flags: Int)
            : super(taskList, task) {
        this.fileName = fileName
        this.eTag = eTag
        this.flags = flags
    }

    private constructor(taskList: DmfsTaskList<*>, values: ContentValues): super(taskList) {
        id = values.getAsLong(Tasks._ID)
        fileName = values.getAsString(Tasks._SYNC_ID)
        eTag = values.getAsString(COLUMN_ETAG)
        flags = values.getAsInteger(COLUMN_FLAGS) ?: 0
    }


    /* process LocalTask-specific fields */

    override fun buildTask(builder: BatchOperation.CpoBuilder, update: Boolean) {
        super.buildTask(builder, update)

        builder .withValue(Tasks._SYNC_ID, fileName)
                .withValue(COLUMN_ETAG, eTag)
                .withValue(COLUMN_FLAGS, flags)
    }


    /* custom queries */

    override fun prepareForUpload(): String {
        val uid: String = task!!.uid ?: run {
            // generate new UID
            val newUid = UUID.randomUUID().toString()

            // update in tasks provider
            val values = contentValuesOf(Tasks._UID to newUid)
            taskList.provider.update(taskSyncURI(), values, null, null)

            // update this task
            task!!.uid = newUid

            newUid
        }

        return "$uid.ics"
    }

    override fun clearDirty(fileName: Optional<String>, eTag: String?, scheduleTag: String?) {
        if (scheduleTag != null)
            logger.fine("Schedule-Tag for tasks not supported yet, won't save")

        val values = ContentValues(4)
        if (fileName.isPresent)
            values.put(Tasks._SYNC_ID, fileName.get())
        values.put(COLUMN_ETAG, eTag)
        values.put(Tasks.SYNC_VERSION, task!!.sequence)
        values.put(Tasks._DIRTY, 0)
        taskList.provider.update(taskSyncURI(), values, null, null)

        if (fileName.isPresent)
            this.fileName = fileName.get()
        this.eTag = eTag
    }

    override fun update(data: Task, fileName: String?, eTag: String?, scheduleTag: String?, flags: Int) {
        this.fileName = fileName
        this.eTag = eTag
        this.scheduleTag = scheduleTag
        this.flags = flags

        // processes this.{fileName, eTag, scheduleTag, flags} and resets DIRTY flag
        update(data)
    }

    override fun updateFlags(flags: Int) {
        if (id != null) {
            val values = contentValuesOf(COLUMN_FLAGS to flags)
            taskList.provider.update(taskSyncURI(), values, null, null)
        }

        this.flags = flags
    }

    override fun deleteLocal() {
        delete()
    }

    override fun resetDeleted() {
        throw NotImplementedError()
    }


    object Factory: DmfsTaskFactory<LocalTask> {
        override fun fromProvider(taskList: DmfsTaskList<*>, values: ContentValues) =
                LocalTask(taskList, values)
    }
}