package net.buzzert.kordophone.backend.model

import android.net.Uri
import com.google.gson.annotations.SerializedName
import java.io.InputStream
import java.util.Date
import java.util.UUID

data class Message(
    @SerializedName("guid")
    val guid: GUID,

    @SerializedName("text")
    val text: String,

    @SerializedName("sender")
    val sender: String?, // optional: nil means "from me"

    @SerializedName("date")
    val date: Date,

    @SerializedName("fileTransferGUIDs")
    val attachmentGUIDs: List<String>?,

    @Transient
    var conversation: Conversation,
) {
    companion object {
        fun generate(text: String, conversation: Conversation = Conversation.generate(), sender: String? = null): Message {
            return Message(
                guid = UUID.randomUUID().toString(),
                text = text,
                sender = sender,
                date = Date(),
                attachmentGUIDs = emptyList(),
                conversation = conversation,
            )
        }
    }

    val displayText: String get() {
        // Filter out attachment markers
        val attachmentMarker = byteArrayOf(0xEF.toByte(), 0xBF.toByte(), 0xBC.toByte()).decodeToString()
        return text.replace(attachmentMarker, "")
    }

    override fun toString(): String {
        return "Message(guid=$guid, text=$text, sender=$sender, date=$date, parent=${conversation.guid})"
    }

    override fun equals(other: Any?): Boolean {
        if (other == null || javaClass != other.javaClass) return false

        val o = other as Message
        return (
            guid == o.guid &&
            text == o.text &&
            sender == o.sender &&
            date == o.date &&
            conversation.guid == o.conversation.guid
        )
    }

    override fun hashCode(): Int {
        var result = guid.hashCode()
        result = 31 * result + text.hashCode()
        result = 31 * result + (sender?.hashCode() ?: 0)
        result = 31 * result + date.hashCode()
        result = 31 * result + conversation.guid.hashCode()
        return result
    }
}

data class UploadingAttachmentMetadata(
    val inputStream: InputStream,
    val mimeType: String,
    val filename: String,
)

data class OutgoingMessage(
    val body: String,
    val conversation: Conversation,
    val attachmentUris: Set<Uri>,
    val attachmentDataSource: (Uri) -> UploadingAttachmentMetadata?
) {
    val guid: String = UUID.randomUUID().toString()

    fun asMessage(): Message {
        return Message(
            guid = guid,
            text = body,
            sender = null,
            date = Date(),
            attachmentGUIDs = listOf(), // TODO: What to do here?
            conversation = conversation
        )
    }
}

