#!/bin/bash
#set -eu

##################
#### GENERAL #####
##################

CAPSULE_DIR=""

# PERCENT-ENCODING
encode_precent_encoding(){
	url=$(echo "$1"|awk '{gsub(/ /,"%20");print}')
	echo "$url"
}
decode_percent_encoding(){
	echo "$1" | sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
}

#################
#### GEMINI #####
#################

# FILE FORMATING OPTIONS
raw2gmi_print(){
	printf "20 text/gemini\r\n"
	cat "$1"
}
raw2gmi_dump(){
	echo '```'
	cat "$1"
	echo '```'
}
txt2gmi_print(){
	printf "20 text/gemini\r\n"
	awk '{printf "%s\n\n",$0}' "$1"
}
txt2gmi_dump(){
	awk '{printf "%s\n\n",$0}' "$1"
}
gmi2gmi_print(){
	printf "20 text/gemini\r\n"
	cat "$1"
}
gmi2gmi_dump(){
	cat "$1"
}

# PHARSING
link2gmi(){
# Pharse a link indicated by "=>path [optional title]"
# Parameter: string of the form "=>path [optional title]"
	line="$1"
	path=$(echo "${line:2}" | awk '{print $1}')
	path="$CAPSULE_DIR$path"
	# File
	if [[ -f "$path" ]]; then
		ext=$(echo "$path"|awk -F'.' '{print $NF}')
		case $ext in
			capsule)
				title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
				title_enc=$(encode_precent_encoding "$title")
				echo "=>main.cgi?capsule=$path $title"
			;;
			*)
				echo "=>$CAPSULE_DIR${line:2}"
			;;
		esac
	fi
	# Directory
	if [[ -d "$path" ]]; then
		title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
		title_enc=$(encode_precent_encoding "$title")
		echo "=>main.cgi?open=$path&title=$title_enc $title"
	fi
	# External link
	if [[ "${line:0:11}" == "=>gemini://" ]];then
		echo "$line"
	fi
}
dump2gmi(){
# Dump the content indicated by "<=path [optional title]"
# Parameter: string of the form "<=path [optional title]"
	content=$(echo "${line:2}" | awk '{print $1}')
	content="$CAPSULE_DIR$content"
	# Directory
	if [[ -d "$content" ]]; then
		header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
		if [[ "$header" != "" ]]; then
			echo "$header"
		fi
		while read item
		do
			ext=$(echo "${item}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					label=$(head -n1 "$content/$item"|awk -F':' '{print $2}')
					if [[ "$label" != "" ]]; then
						echo "=>main.cgi?print=$content/$item $label"
					else
						echo "=>main.cgi?print=$content/$item $item"
					fi
				;;
				gmi)
					label=$(head -n1 "$content/$item" | awk '{print substr($0,2)}')
					echo "=>main.cgi?print=$content/$item $label"
				;;
				text)
					label="$item"
					echo "=>main.cgi?print=$content/$item $label"
				;;
			esac
		done < <(ls -1A "$content")
	else
		# File
		if [[ -f "$content" ]]; then
			header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
			if [[ "$header" != "" ]]; then
				printf "$header\r\n"
			fi
			ext=$(echo "${content}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					txt2gmi_dump "$content"
				;;
				gmi)
					gmi2gmi_dump "$content"
				;;
				*)
					raw2gmi_dump "$content"
				;;
			esac
		fi
	fi
}

# OPTIONS
print_gmi(){
# Wehn QUERY_STRING="print=path"
# Parameter: path
	path="$1"
	path_dec=$(decode_percent_encoding "$path")
	# Get file extension.
	ext=$(echo "$path"|awk -F"." '{print $NF}')
	case $ext in
		txt)
			txt2gmi_print "$path_dec"
		;;
		gmi)
			gmi2gmi_print "$path_dec"
		;;
		*)
			raw2gmi_print "$path_dec"
		;;
	esac
}
open_gmi(){
# When QUERY_STRING="open=dir&title=title"
# Parameters: dir title
	dir="$1"
	title="$2"
	dir_clean=$(decode_percent_encoding "$dir")
	title_clean=$(decode_percent_encoding "$title")
	printf "20 text/gemini\r\n"
	echo "# $title_clean"
		while read item
		do
			ext=$(echo "${item}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					label=$(head -n1 "$dir_clean/$item"|awk -F':' '{print $2}')
				;;
				gmi)
					label=$(head -n1 "$dir_clean/$item")
					t="${label:2}"
					label="$t"
				;;
				*)
					label="$item"
				;;
			esac
			echo "=>main.cgi?print=$dir_clean/$item $label"
		done < <(ls -1A "$dir_clean")
}

# DEPLOY FUNCTIONS
deploy_gmi(){
# Deploy gemini capsule
# Parameter: .capsule file
	capsule="$1"
	printf "20 text/gemini\r\n"
	while IFS= read line
	do
		## Link content indicated by "=>"
		if [[ "${line:0:2}" == "=>" ]]; then
			link2gmi "$line"
		fi
		# Dump the content indicated by "<="
		if [[ "${line:0:2}" == "<=" ]]; then
			dump2gmi "$line"
		fi
		# Any other line
		if [[ "${line:0:2}" != "=>" ]] && [[ "${line:0:2}" != "<=" ]]; then
			echo -E "$line"
		fi
	done < "$capsule"
}

#################
#### GOPHER #####
#################

# FILE FORMATING OPTIONS
raw2gopher_print(){
	fmt -s -w 60 "$1"
}
raw2gopher_dump(){
	fmt -s -w 60 "$1"
}
txt2gopher_print(){
	awk '{printf "%s\n\n",$0}' "$1" | fmt -s -w 60
}
txt2gopher_dump(){
	awk '{printf "%s\n\n",$0}' "$1" | fmt -s -w 60
}
gmi2gopher_print(){
	fmt -s -w 60 "$1"
}
gmi2gopher_dump(){
	fmt -s -w 60 "$1"
}

# PHARSING
link2gopher(){
# Pharse a link indicated by "=>path [optional title]"
# Parameter: string of the form "=>path [optional title]"
	line="$1"
	path=$(echo "${line:2}" | awk '{print $1}')
	path="$CAPSULE_DIR$path"
	# File
	if [[ -f "$path" ]]; then
		ext=$(echo "$path"|awk -F'.' '{print $NF}')
		case $ext in
			capsule)
				title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
				title_enc=$(encode_precent_encoding "$title")
				printf "0$title\t$GOPHER_DIR/main.cgi?capsule=$path\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
				#echo "=>main.cgi?capsule=$path $title"
			;;
			*)
				title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
				title_enc=$(encode_precent_encoding "$title")
				printf "0$title\t$GOPHER_DIR/$path\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
				#echo "=>$CAPSULE_DIR${line:2}"
			;;
		esac
	fi
	# Directory
	if [[ -d "$path" ]]; then
		title=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
		title_enc=$(encode_precent_encoding "$title")
		printf "0$title\t$GOPHER_DIR/main.cgi?open=$path&title=$title_enc\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
		#echo "=>main.cgi?open=$path&title=$title_enc $title"
	fi
	# External link
	if [[ "${line:0:11}" == "=>gemini://" ]]; then
		echo "$line"
	fi
}
dump2gopher(){
# Dump the content indicated by "<=path [optional title]"
# Parameter: string of the form "<=path [optional title]"
	content=$(echo "${line:2}" | awk '{print $1}')
	content="$CAPSULE_DIR$content"
	# Directory
	if [[ -d "$content" ]]; then
		header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
		if [[ "$header" != "" ]]; then
			echo "$header"
		fi
		while read item
		do
			ext=$(echo "${item}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					label=$(head -n1 "$content/$item"|awk -F':' '{print $2}')
					if [[ "$label" != "" ]]; then
						printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
						#echo "=>main.cgi?print=$content/$item $label"
					else
						printf "0$item\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
						#echo "=>main.cgi?print=$content/$item $item"
					fi
				;;
				gmi)
					label=$(head -n1 "$content/$item" | awk '{print substr($0,2)}')
					printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
					#echo "=>main.cgi?print=$content/$item $label"
				;;
				text)
					label="$item"
					printf "0$label\t$GOPHER_DIR/main.cgi?print=$content/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
					#echo "=>main.cgi?print=$content/$item $label"
				;;
			esac
		done < <(ls -1A "$content")
	else
		# File
		if [[ -f "$content" ]]; then
			header=$(echo "${line:2}" | awk '{match($0,/ /);print substr($0,RSTART+1)}')
			if [[ "$header" != "" ]]; then
				printf "$header\r\n"
			fi
			ext=$(echo "${content}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					txt2gopher_dump "$content"
				;;
				gmi)
					gmi2gopher_dump "$content"
				;;
				*)
					raw2gopher_dump "$content"
				;;
			esac
		fi
	fi
}

# OPTIONS
print_gopher(){
# Wehn QUERY_STRING="print=path"
# Parameter: path
	path="$1"
	path_dec=$(decode_percent_encoding "$path")
	# Get file extension.
	ext=$(echo "$path"|awk -F"." '{print $NF}')
	case $ext in
		txt)
			txt2gopher_print "$path_dec"
		;;
		gmi)
			gmi2gopher_print "$path_dec"
		;;
		*)
			raw2gopher_print "$path_dec"
		;;
	esac
}
open_gopher(){
# When QUERY_STRING="open=dir&title=title"
# Parameters: dir title
	dir="$1"
	title="$2"
	dir_clean=$(decode_percent_encoding "$dir")
	title_clean=$(decode_percent_encoding "$title")
	printf "20 text/gemini\r\n"
	echo "# $title_clean"
		while read item
		do
			ext=$(echo "${item}"|awk -F"." '{print $NF}')
			case $ext in
				txt)
					label=$(head -n1 "$dir_clean/$item"|awk -F':' '{print $2}')
				;;
				gmi)
					label=$(head -n1 "$dir_clean/$item")
					t="${label:2}"
					label="$t"
				;;
				*)
					label="$item"
				;;
			esac
			printf "0$label\t$GOPHER_DIR/main.cgi?print=$dir_clean/$item\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
			#echo "=>main.cgi?print=$dir_clean/$item $label"
		done < <(ls -1A "$dir_clean")
}

# DEPLOY FUNCTIONS
deploy_gopher(){
# Deploy gemini capsule
# Parameter: .capsule file
	capsule="$1"
	printf "20 text/gemini\r\n"
	while IFS= read line
	do
		## Link content indicated by "=>"
		if [[ "${line:0:2}" == "=>" ]]; then
			link2gopher "$line"
		fi
		# Dump the content indicated by "<="
		if [[ "${line:0:2}" == "<=" ]]; then
			dump2gopher "$line"
		fi
		# Any other line
		if [[ "${line:0:2}" != "=>" ]] && [[ "${line:0:2}" != "<=" ]]; then
			echo "$line"
		fi
	done < "$capsule"
}

####################
#### DEPLOYMENT ####
####################

# DEPLY CAPSULE/GOPHERHOLE
# Gemini
if [[ "$SERVER_PROTOCOL" == "GEMINI" ]]; then
	# Print a file if QUERY_STRING="print=..."
	if [[ "${QUERY_STRING:0:5}" == "print" ]]; then
		path="${QUERY_STRING:6}"
		print_gmi "$path"
	else
		# Open a directory if QUERY_STRING="open=dir&title=title"
		if [[ "${QUERY_STRING:0:4}" == "open" ]]; then
			dir=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print $1}')
			title=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print substr($2,7)}')
			open_gmi "$dir" "$title"
		else
			# Deploy a specific capsule if QUERY_STRING="capsule=capsule"
			if [[ "${QUERY_STRING:0:7}" == "capsule" ]]; then
				capsule="${QUERY_STRING:8}"
				capsule_clean=$(decode_percent_encoding "${QUERY_STRING:8}")
				CAPSULE_DIR="$(dirname "$capsule_clean")"
				if [[ "$CAPSULE_DIR" != "" ]]; then
					CAPSULE_DIR="$CAPSULE_DIR/"
				fi
				#CAPSULE_DIR="lala"
				#CAPSULE_DIR="${capsule_clean%/*}"
				#deploy_gmi "$capsule_clean"
				deploy_gmi "$capsule_clean"
			else
				deploy_gmi "main.capsule"
			fi
		fi
	fi
fi
# Gopher
GOPHER_DIR="/~filip/public_gemini"
GOPHER_SERVER="tilde.club"
GOPHER_PORT="70"
if [[ "$SERVER_PROTOCOL" == "RFC1436" ]]; then
	echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	echo "You are opening a Gemini capsule via Gopher!"
	echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
	# Print a file if QUERY_STRING="print=..."
	if [[ "${QUERY_STRING:0:5}" == "print" ]]; then
		path="${QUERY_STRING:6}"
		print_gopher "$path"
	else
		# Open a directory if QUERY_STRING="open=dir&title=title"
		if [[ "${QUERY_STRING:0:4}" == "open" ]]; then
			dir=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print $1}')
			title=$(echo "${QUERY_STRING:5}"|awk -F"&" '{print substr($2,7)}')
			open_gopher "$dir" "$title"
		else
			# Deploy a specific capsule if QUERY_STRING="capsule=capsule"
			if [[ "${QUERY_STRING:0:7}" == "capsule" ]]; then
				capsule="${QUERY_STRING:8}"
				capsule_clean=$(decode_percent_encoding "${QUERY_STRING:8}")
				CAPSULE_DIR="$(dirname "$capsule_clean")"
				if [[ "$CAPSULE_DIR" != "" ]]; then
					CAPSULE_DIR="$CAPSULE_DIR/"
				fi
				#CAPSULE_DIR="lala"
				#CAPSULE_DIR="${capsule_clean%/*}"
				#deploy_gmi "$capsule_clean"
				deploy_gopher "$capsule_clean"
			else
				deploy_gopher "main.capsule"
			fi
		fi
	fi
fi
#if [[ "$SERVER_PROTOCOL" == "RFC1436" ]]; then
#echo "You are using Gopher!"
#
#	printf "0TITLE\t$GOPHER_DIR/file\t$GOPHER_SERVER\t$GOPHER_PORT\r\n"
#	printf "0gemini\t$GOPHER_DIR/gemini/gemini.gmi\ttilde.club\t70\r\n"
	#printf "0gemini\t/~filip/public_gemini/gemini/gemini.gmi\ttilde.club\t70\r\n"
#	printf "0gemini\t/~filip/cgi-bin/public_gemini/gemini/gemini.gmi\ttilde.club\t70"
#fi