ClipboardService.kt

package de.pflugradts.passbird.adapter.clipboard
import de.pflugradts.kotlinextensions.tryCatching
import de.pflugradts.passbird.application.ClipboardAdapterPort
import de.pflugradts.passbird.application.configuration.ReadableConfiguration
import de.pflugradts.passbird.application.failure.ClipboardFailure
import de.pflugradts.passbird.application.failure.reportFailure
import de.pflugradts.passbird.domain.model.transfer.Output
private const val MILLI_SECONDS = 1000L
class ClipboardService constructor(
    private val clipboardGateway: ClipboardGateway,
    private val configuration: ReadableConfiguration,
) : ClipboardAdapterPort {
    private val cleanerLock = Any()
    private var cleanerGeneration = 0L
    override fun post(output: Output) = tryCatching {
        synchronized(cleanerLock) {
            clipboardGateway.copy(output.shell.asString())
            cleanerGeneration += 1
            cleanerGeneration
        }
    }.onFailure {
        reportFailure(ClipboardFailure(it))
    }.onSuccess(::scheduleCleaner).map {
        Unit
    }
    private fun scheduleCleaner(generation: Long) {
        if (isResetEnabled) {
            Thread {
                sleep()
                    .onSuccess { clearClipboard(generation) }
                    .onFailure { reportFailure(ClipboardFailure(it)) }
            }.start()
        }
    }

    private fun clearClipboard(generation: Long) {
        synchronized(cleanerLock) {
            if (cleanerGeneration == generation) {
                tryCatching { clipboardGateway.copy("") }.onFailure { reportFailure(ClipboardFailure(it)) }
            }
        }
    }

    private fun sleep() = tryCatching { Thread.sleep(delaySeconds * MILLI_SECONDS) }
    private val isResetEnabled: Boolean get() = configuration.adapter.clipboard.reset.enabled
    private val delaySeconds: Int get() = configuration.adapter.clipboard.reset.delaySeconds
}