package eu.gaudian.translator.utils


object PunctuationPreserver {

    // Punctuation that should have a space after
    private val requiresSpaceAfter = setOf(',', ';', ':')

    // Punctuation that in some languages commonly has a space before it (e.g., French)
    private val mayRequireSpaceBefore = setOf('?', '!', ';', ':')

    fun preserveSpacing(original: String, translated: String): String {
        if (original.isBlank() || translated.isBlank()) return translated

        var result = translated

        // 1) If original has space before any of the specified marks, ensure translated also has one
        for (mark in mayRequireSpaceBefore) {
            val origHas = originalHasSpaceBefore(original, mark)
            if (origHas) {
                result = ensureSpaceBefore(result, mark)
            }
        }

        // 2) If original has a space after commas/semicolons/colons, ensure translated also has one
        for (mark in requiresSpaceAfter) {
            val origHas = originalHasSpaceAfter(original, mark)
            if (origHas) {
                result = ensureSpaceAfter(result, mark)
            }
        }

        return result
    }

    private fun originalHasSpaceBefore(text: String, ch: Char): Boolean {
        var i = text.indexOf(ch)
        while (i >= 0) {
            if (i > 0 && text[i - 1].isWhitespace()) return true
            i = text.indexOf(ch, i + 1)
        }
        return false
    }

    private fun originalHasSpaceAfter(text: String, ch: Char): Boolean {
        var i = text.indexOf(ch)
        while (i >= 0) {
            if (i < text.lastIndex && text[i + 1].isWhitespace()) return true
            i = text.indexOf(ch, i + 1)
        }
        return false
    }

    private fun ensureSpaceBefore(text: String, ch: Char): String {
        // Replace occurrences of X where directly preceded by non-space with space
        // Patterns: "word?" -> "word ?"; also handle cases with multiple punctuation.
        val sb = StringBuilder()
        var i = 0
        while (i < text.length) {
            val c = text[i]
            if (c == ch) {
                // if there is no space before, add one (but avoid adding at start)
                if (i > 0 && !text[i - 1].isWhitespace()) {
                    sb.append(' ')
                }
                sb.append(c)
                i++
            } else {
                sb.append(c)
                i++
            }
        }
        return sb.toString()
    }

    private fun ensureSpaceAfter(text: String, ch: Char): String {
        val sb = StringBuilder()
        var i = 0
        while (i < text.length) {
            val c = text[i]
            sb.append(c)
            if (c == ch) {
                val next = if (i + 1 <= text.lastIndex) text[i + 1] else null
                if (next != null && !next.isWhitespace()) {
                    sb.append(' ')
                }
            }
            i++
        }
        return sb.toString()
    }
}