/*
 * This file is part of LibEuFin.
 * Copyright (C) 2024 Taler Systems S.A.
 *
 * LibEuFin is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation; either version 3, or
 * (at your option) any later version.
 *
 * LibEuFin is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
 * Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with LibEuFin; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>
 */

package tech.libeufin.common

object ANSI {
    private val ANSI_PATTERN = Regex("\\u001B\\[[;\\d]*m")

    enum class Color(val code: Int) {
        BLACK(0),
        RED(1),
        GREEN(2),
        YELLOW(3),
        BLUE(4),
        MAGENTA(5),
        CYAN(6),
        WHITE(7)
    }

    /** Compute [msg] length without ANSI escape sequences */
    fun CharSequence.displayLength(): Int =
        splitToSequence(ANSI_PATTERN).sumOf { it.length }

    /** Format a [msg] using optionals [fg] and [bg] colors and optionally make the text [bold] */
    fun fmt(msg: String, fg: Color? = null, bg: Color? = null, bold: Boolean = false): String {
        if (fg == null && bg == null && !bold) return msg
        return buildString {
            fun next() {
                if (last() != '[') {
                    append(';')
                }
            }

            append("\u001b[")
            if (bold) {
                append('1')
            }
            if (fg != null) {
                next()
                append('3')
                append(fg.code.toString())
            }
            if (bg != null) {
                next()
                append('4')
                append(bg.code.toString())
            }
            append('m')
            append(msg)
            append("\u001b[0m")
        }
    }

    fun red(msg: String) = fmt(msg, Color.RED)
    fun green(msg: String) = fmt(msg, Color.GREEN)
    fun yellow(msg: String) = fmt(msg, Color.YELLOW)
    fun magenta(msg: String) = fmt(msg, Color.MAGENTA)
    fun bold(msg: String) = fmt(msg, bold = true)
}