#!/usr/bin/awk -f
# Copyright (c) 2022 Robin Jarry
#
# A filter for the aerc mail program to colorize messages / attachments.
# Basic colour themes are supported. To use a theme set the theme variable
# in your aerc.conf accordingly, for example:
#
# text/plain=colorize -v theme=solarized

BEGIN {
	if (theme == "solarized") {
		# R;G;B colors
		url = "\033[38;2;181;137;0m" # yellow
		header = "\033[38;2;211;54;130m" # magenta
		signature = "\033[38;2;211;54;130m" # magenta
		diff_meta = "\033[1;38;2;131;148;150m" # bold brblue
		diff_chunk = "\033[38;2;42;161;152m" # cyan
		diff_add = "\033[38;2;133;153;0m" # green
		diff_del = "\033[38;2;220;50;47m" # red
		quote_1 = "\033[38;2;38;139;210m"  # blue
		quote_2 = "\033[38;2;203;75;22m" # brred
		quote_3 = "\033[38;2;211;54;130m" # magenta
		quote_4 = "\033[38;2;108;113;196m" # brmagenta
		quote_x = "\033[38;2;147;161;161m" # brcyan
		bold = "\033[1m"
		reset = "\033[0m"
	} else if (theme == "" || theme == "default") {
		# R;G;B colors
		url = "\033[38;2;255;255;175m" # yellow
		header = "\033[38;2;175;135;255m" # purple
		signature = "\033[38;2;175;135;255m" # purple
		diff_meta = "\033[1;38;2;255;255;255m" # bold white
		diff_chunk = "\033[38;2;0;205;205m" # cyan
		diff_add = "\033[38;2;0;205;0m" # green
		diff_del = "\033[38;2;205;0;0m" # red
		quote_1 = "\033[38;2;95;175;255m"  # blue
		quote_2 = "\033[38;2;255;135;0m" # orange
		quote_3 = "\033[38;2;175;135;255m" # purple
		quote_4 = "\033[38;2;255;95;215m" # pink
		quote_x = "\033[38;2;128;128;128m" # gray
		bold = "\033[1m"
		reset = "\033[0m"
	} else if (theme == "terminal") {
		# terminal respects the users configured terminal color theme
		url = "\033[4;34m" # underline blue
		header = "\033[35m" # magenta
		signature = "\033[35m" # magenta
		diff_meta = "\033[2m" # faint
		diff_chunk = "\033[36m" # cyan
		diff_add = "\033[32m" # green
		diff_del = "\033[31m" # red
		quote_1 = "\033[37m"  # grey
		quote_2 = "\033[34m" # blue
		quote_3 = "\033[2;37m" # faint grey
		quote_4 = "\033[2;34m" # faint blue
		quote_x = "\033[2;37m" # faint grey
		bold = "\033[1m"
		reset = "\033[0m"
	} else {
		print "error: unknown theme " theme > "/dev/stderr"
		exit 1
	}
	# state
	in_diff = 0
	in_signature = 0
	in_headers = 0
	in_body = 0
	# patterns
	header_pattern = "^[A-Z][[:alnum:]-]+:"
	url_pattern = "[[:lower:]]+://[[:graph:]]+|(mailto:)?[[:alnum:]_\\+\\.~/-]*[[:alnum:]_]@[[:lower:]][[:alnum:]\\.-]*[[:lower:]]"
	meta_pattern = "^(diff --git|(new|deleted) file|similarity index|(rename|copy) (to|from)|index|---|\\+\\+\\+) "
}
function color_quote(line) {
	level = 0
	quotes = ""
	while (line ~ /^>/) {
		level += 1
		quotes = quotes ">"
		line = substr(line, 2)
		while (line ~ /^ /) {
			quotes = quotes " "
			line = substr(line, 2)
		}
	}
	if (level == 1) {
		color = quote_1
	} else if (level == 2) {
		color = quote_2
	} else if (level == 3) {
		color = quote_3
	} else if (level == 4) {
		color = quote_4
	} else {
		color = quote_x
	}
	if (match(line, meta_pattern)) {
		return color quotes bold line reset
	} else if (line ~ /^\+/) {
		return color quotes diff_add line reset
	} else if (line ~ /^-/) {
		return color quotes diff_del line reset
	}
	gsub(url_pattern, url "&" color, line)
	return color quotes line reset
}
{
	# Strip carriage returns from line
	sub(/\r$/, "")

	if (in_diff) {
		if ($0 ~ /^-- ?$/) {
			in_diff = 0
			in_signature = 1
			$0 = signature $0 reset
		} else if ($0 ~ /^@@ /) {
			gsub(/^@@[^@]+@@/, diff_chunk "&" reset)
		} else if (match($0, meta_pattern)) {
			$0 = diff_meta $0 reset
		} else if ($0 ~ /^\+/) {
			$0 = diff_add $0 reset
		} else if ($0 ~ /^-/) {
			$0 = diff_del $0 reset
		} else if ($0 !~ /^ / && $0 !~ /^$/) {
			in_diff = 0
			in_body = 1
			if ($0 ~ /^>/) {
				$0 = color_quote($0)
			} else {
				gsub(url_pattern, url "&" reset)
			}
		}
	} else if (in_signature) {
		gsub(url_pattern, url "&" signature)
		$0 = signature $0 reset
	} else if (in_headers) {
		if ($0 ~ /^$/) {
			in_headers = 0
			in_body = 1
		} else {
			sub(header_pattern, header "&" reset)
			gsub(url_pattern, url "&" reset)
		}
	} else if (in_body) {
		if ($0 ~ /^>/) {
			$0 = color_quote($0)
		} else if ($0 ~ /^diff --git /) {
			in_body = 0
			in_diff = 1
			$0 = diff_meta $0 reset
		} else if ($0 ~ /^-- ?$/) {
			in_body = 0
			in_signature = 1
			$0 = signature $0 reset
		} else {
			gsub(url_pattern, url "&" reset)
		}
	} else if ($0 ~ /^diff --git /) {
		in_diff = 1
		$0 = diff_meta $0 reset
	} else if ($0 ~ /^-- ?$/) {
		in_signature = 1
		$0 = signature $0 reset
	} else if (match($0, header_pattern)) {
		in_headers = 1
		sub(header_pattern, header "&" reset)
		gsub(url_pattern, url "&" reset)
	} else {
		in_body = 1
		if ($0 ~ /^>/) {
			$0 = color_quote($0)
		} else {
			gsub(url_pattern, url "&" reset)
		}
	}

	print
}
