#!/usr/bin/env bash

### Helpers begin
check_deps() {
    local missing
    for d in "${deps[@]}"; do
        if [[ -z $(command -v "$d") ]]; then
            # Force absolute path
            if [[ ! -e "/$d" ]]; then
                err "$d was not found"
                missing="true"
            fi
        fi
    done; unset d
    [[ -z $missing ]] || exit 128
}
err() { echo -e "${color:+\e[31m}[!] $*\e[0m"; }
errx() { err "${*:2}"; exit "$1"; }
good() { echo -e "${color:+\e[32m}[+] $*\e[0m"; }
info() { echo -e "${color:+\e[37m}[*] $*\e[0m"; }
long_opt() {
    local arg shift="0"
    case "$1" in
        "--"*"="*) arg="${1#*=}"; [[ -n $arg ]] || return 127 ;;
        *) shift="1"; shift; [[ $# -gt 0 ]] || return 127; arg="$1" ;;
    esac
    echo "$arg"
    return $shift
}
subinfo() { echo -e "${color:+\e[36m}[=] $*\e[0m"; }
warn() { echo -e "${color:+\e[33m}[-] $*\e[0m"; }
### Helpers end

generate_ansi_funcs() {
    local code="$1"
    local func="$(echo "${code^}" | sed -r "s/_(.)/\u\1/g")"

    cat <<EOF
// $func will Hilight() the provided string with the
// specified ANSI code.
func $func(str string) string {
    return Hilight("$code", str)
}

$(generate_print_funcs "$func" "")

EOF
}

generate_print_funcs() {
    local func="$1"
    local var="${2:+${2%% *}, }"
    local vardef="${2:+$2, }"

    cat <<EOF
// ${func}f wraps fmt.Sprintf() and $func.
func ${func}f(${vardef}format string, args ...any) string {
    return $func(${var}Sprintf(format, args...))
}

// Fprint$func wraps $func() and fmt.Fprint().
func Fprint$func(w io.Writer, ${vardef}str string) {
    Fprint(w, $func(${var}str))
}

// Fprintf$func wraps $func and fmt.Fprintf().
func Fprintf$func(w io.Writer, ${vardef}format string, args ...any) {
    Fprint$func(w, ${var}Sprintf(format, args...))
}

// Fprintln$func wraps $func() and fmt.Fprintln().
func Fprintln$func(w io.Writer, ${vardef}str string) {
    Fprintln(w, $func(${var}str))
}

// Print$func wraps $func() and fmt.Print().
func Print$func(${vardef}str string) {
    Print($func(${var}str))
}

// Printf$func wraps $func() and fmt.Printf().
func Printf$func(${vardef}format string, args ...any) {
    Print$func(${var}Sprintf(format, args...))
}

// Println$func wraps $func() and fmt.Println().
func Println$func(${vardef}str string) {
    Println($func(${var}str))
}
EOF
}

usage() {
    cat <<EOF
Usage: ${0##*/} [OPTIONS]

DESCRIPTION
    Create autogenerated_colors.go.

OPTIONS
    -h, --help        Display this help message
        --no-color    Disable colorized output

EOF
    exit "$1"
}

declare -a args
unset help
color="true"

# Parse command line options
while [[ $# -gt 0 ]]; do
    case "$1" in
        "--") shift; args+=("$@"); break ;;
        "-h"|"--help") help="true" ;;
        "--no-color") unset color ;;
        *) args+=("$1") ;;
    esac
    case "$?" in
        0) ;;
        1) shift ;;
        *) usage $? ;;
    esac
    shift
done
[[ ${#args[@]} -eq 0 ]] || set -- "${args[@]}"

# Help info
[[ -z $help ]] || usage 0

# Check for missing dependencies
declare -a deps
deps+=("go")
deps+=("sed")
check_deps

# Check for valid params
[[ $# -eq 0 ]] || usage 1

file="generated.go"

cat >"$file" <<EOF
// Code generated by ${0#./}; DO NOT EDIT.
package hilighter

import "io"

$(
    for color in black red green yellow blue magenta cyan white; do
        generate_ansi_funcs "$color"
        generate_ansi_funcs "on_$color"
        generate_ansi_funcs "light_$color"
        generate_ansi_funcs "on_light_$color"
    done; unset color

    generate_ansi_funcs default
    generate_ansi_funcs on_default

    for i in $(seq -w 0 255); do
        generate_ansi_funcs "color_$i"
        generate_ansi_funcs "on_color_$i"
    done; unset i
)

$(
    generate_ansi_funcs reset
    generate_ansi_funcs normal

    for mode in \
        bold dim faint italic underline blink blink_slow blink_rapid \
        inverse negative swap hide conceal crossed_out strikethrough \
        fraktur
    do
        generate_ansi_funcs "$mode"
        generate_ansi_funcs "no_$mode"
    done; unset mode
)

$(
    generate_print_funcs "Hex" "hex string"
    generate_print_funcs "Hilight" "code string"
    generate_print_funcs "Hilights" "codes []string"
    generate_print_funcs "OnHex" "hex string"
    generate_print_funcs "OnRainbow" ""
    generate_print_funcs "Plain" ""
    generate_print_funcs "Rainbow" ""
    generate_print_funcs "Wrap" "width int"
)
EOF
#$(
#    generate_ansi_funcs "green"
#    generate_print_funcs "Hex" "hex string"
#)

go fmt "$file" >/dev/null
