package me.eternal.purrfectsnap.core.features

import me.eternal.purrfectsnap.common.bridge.FileHandleScope
import me.eternal.purrfectsnap.common.bridge.InternalFileHandleType
import me.eternal.purrfectsnap.common.bridge.toWrapper
import me.eternal.purrfectsnap.common.util.LazyBridgeValue
import me.eternal.purrfectsnap.common.util.mappedLazyBridge
import java.io.BufferedReader
import java.io.InputStreamReader
import java.nio.charset.StandardCharsets

abstract class BridgeFileFeature(name: String, private val bridgeFileType: InternalFileHandleType) : Feature(name) {
    private val fileLines = mutableListOf<String>()
    private val fileWrapper by mappedLazyBridge(LazyBridgeValue({ context.fileHandlerManager.getFileHandle(FileHandleScope.INTERNAL.key, bridgeFileType.key)!! }), map = { it.toWrapper() })

    private fun readFile() {
        val temporaryLines = mutableListOf<String>()
        fileWrapper.inputStream { stream ->
            with(BufferedReader(InputStreamReader(stream, StandardCharsets.UTF_8))) {
                var line = ""
                while (readLine()?.also { line = it } != null) temporaryLines.add(line)
                close()
            }
        }

        fileLines.clear()
        fileLines.addAll(temporaryLines)
    }

    private fun updateFile() {
        fileWrapper.outputStream { stream ->
            fileLines.forEach {
                stream.write(it.toByteArray())
                stream.write("\n".toByteArray())
                stream.flush()
            }
        }
    }

    protected fun exists(line: String) = fileLines.contains(line)

    protected fun toggle(line: String) {
        if (exists(line)) fileLines.remove(line) else fileLines.add(line)
        updateFile()
    }

    protected fun setState(line: String, state: Boolean) {
        if (state) {
            if (!exists(line)) fileLines.add(line)
        } else {
            if (exists(line)) fileLines.remove(line)
        }
        updateFile()
    }

    protected fun reload() = readFile()

    protected fun put(line: String) {
        fileLines.add(line)
        updateFile()
    }

    protected fun clear() {
        fileLines.clear()
        updateFile()
    }

    protected fun lines() = fileLines.toList()
}