#!/bin/bash

declare -f kstore > /dev/null
if [ $? -ne 0 ]; then
	echo "kcontext depends on kstore"
	return 1
fi

function kcontext {
	case $1 in
		k8s) shift; _kcontext-k8s "$@" ;;
		s3-arch) shift; _kcontext-s3-arch "$@" ;;
		*)
			__func_head "k8s ..."
			__func_help "s3-arch ..."
			__func_help "docker ..."
			return 1
			;;
	esac
	return $?
}

function _kcontext {
	local cur cmd subcmd
	cur="${COMP_WORDS[COMP_CWORD]}"
	cmd="${COMP_WORDS[1]}"
	subcmd="${COMP_WORDS[2]}"

	COMPREPLY=()

	case "$COMP_CWORD" in
		1)
			COMPREPLY=( $(compgen -W "k8s s3-arch" -- "$cur") )
			return
			;;

		2)
			case "$cmd" in
				k8s)
					COMPREPLY=( $(compgen -W "use del import list save" -- "$cur") )
					return
					;;
				s3-arch)
					COMPREPLY=( $(compgen -W "use del list save" -- "$cur") )
					return
					;;
			esac
			;;
	esac

	case "$cmd:$subcmd" in
		k8s:use|k8s:import|k8s:del|s3-arch:use|s3-arch:del)
			COMPREPLY=( $(compgen -W "$(kcontext "$cmd" list 2>/dev/null)" -- "$cur") )
			return
			;;
	esac
}

complete -F _kcontext kcontext

function _kcontext-k8s {
	local _NAME _CONF _TMP_CONF
	case $1 in
		list)
			kstore query -list "SELECT SUBSTR( prop, 5 ) FROM $_KSTORE_TABLE WHERE key = 'kcontext' AND prop LIKE 'k8s.%'"
			return $?
			;;
		save)
			_NAME=$( kubectl config current-context )
			if [ $? -ne 0 ]; then
				return 1
			fi

			kstore get "kcontext" "k8s.$_NAME" 2> /dev/null > /dev/null
			if [ $? -eq 0 ]; then
				read -p "Replace existing config for \"$_NAME\"? (y/n): " _CONFIRM
				if [ "$_CONFIRM" != "y" ]; then
					return 0
				fi
				kubectl config view --minify --flatten | kstore update "kcontext" - "k8s.$_NAME"
				return $?
			else
				kubectl config view --minify --flatten | kstore add "kcontext" - "k8s.$_NAME"
				return $?
			fi
			;;
		import)
			_NAME=$2
			_CONF=$3

			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi

			if [ -z "$_CONF" ]; then
				echo "Please specify the kube config path, or '-' for stdin" >&2
				return 1
			fi

			_TMP_CONF=$(mktemp "${RBASH_HOME}/k8s.import.XXXXXX") || return 1
			trap 'rm -f "$_TMP_CONF"' RETURN

			if [ "$_CONF" == "-" ]; then
				cat > "$_TMP_CONF"
			elif [ -f "$_CONF" ]; then
				cp "$_CONF" "$_TMP_CONF" || return 1
			else
				echo "Kube config not found: $_CONF" >&2
				return 1
			fi

			if ! KUBECONFIG="$_TMP_CONF" kubectl config view --minify --flatten >/dev/null 2>&1; then
				echo "Invalid kube config: $_CONF" >&2
				return 1
			fi

			if kstore get "kcontext" "k8s.$_NAME" >/dev/null 2>&1; then
				printf "Replace existing config for \"%s\"? (y/n): " "$_NAME" > /dev/tty
				read -r _CONFIRM </dev/tty
				if [ "$_CONFIRM" != "y" ]; then
					return 0
				fi

				KUBECONFIG="$_TMP_CONF" kubectl config view --minify --flatten \
					| kstore update "kcontext" - "k8s.$_NAME"
			else
				KUBECONFIG="$_TMP_CONF" kubectl config view --minify --flatten \
					| kstore add "kcontext" - "k8s.$_NAME"
			fi

			if [ $? -eq 0 ]; then
				_kcontext-k8s use "$_NAME"
				return $?
			fi

			return 1
			;;
		use)
			_NAME=$2
			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi

			_CONF="$RBASH_HOME/k8s.conf"
			kstore get "kcontext" "k8s.$_NAME" > "$_CONF"
			if [ $? -ne 0 ]; then
				echo "No such context: $_NAME" >&2
				return 1
			fi

			chmod 600 "$_CONF"

			case $OSTYPE in
				cygwin)
					_CONF=$(cygpath -w "$_CONF")
					;;
			esac

			case ":$KUBECONFIG:" in
				*":$_CONF:"*)
					export KUBECONFIG="$_CONF"
					;;
				"::")
					export KUBECONFIG="$_CONF"
					;;
				*)
					export KUBECONFIG="$_CONF:$KUBECONFIG"
					;;
			esac
			;;
		del)
			_NAME=$2
			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi
			kstore get "kcontext" "k8s.$_NAME" 2> /dev/null > /dev/null
			if [ $? -eq 0 ]; then
				read -p "Delete context \"$_NAME\"? (y/n): " _CONFIRM
				if [ "$_CONFIRM" != "y" ]; then
					return 0
				fi
				kstore query "DELETE FROM $_KSTORE_TABLE WHERE key = 'kcontext' AND prop = 'k8s.$_NAME'"
				return $?
			else
				echo "No such context: $_NAME" >&2
			fi
			;;
		*)
			__func_head "list"
			__func_help "save"
			__func_help "import NAME FILE"
			__func_help "use NAME"
			__func_help "del NAME"
			;;
	esac
	return 1
}

function _kcontext-s3-arch {
	local _NAME _CONFIRM _URL _AUTH
	case $1 in
		list)
			kstore query -list "SELECT SUBSTR( prop, 16 ) FROM $_KSTORE_TABLE WHERE key = 'kcontext' AND prop LIKE 's3-arch.bucket.%'"
			return $?
			;;
		save)
			_NAME=$2
			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi
			if [ -n "$ARCH_S3_BUCKET_URL" ] && [ -n "$ARCH_S3_AUTH" ]; then
				kstore get "kcontext" "s3-arch.bucket.$_NAME" 2> /dev/null > /dev/null
				if [ $? -eq 0 ]; then
					read -p "Replace existing config for \"$_NAME\"? (y/n): " _CONFIRM
					if [ "$_CONFIRM" != "y" ]; then
						return 0
					fi
					kstore update "kcontext" "$ARCH_S3_BUCKET_URL" "s3-arch.bucket.$_NAME"
					kstore update "kcontext" "$ARCH_S3_AUTH" "s3-arch.auth.$_NAME"
					return $?
				else
					kstore add "kcontext" "$ARCH_S3_BUCKET_URL" "s3-arch.bucket.$_NAME"
					kstore add "kcontext" "$ARCH_S3_AUTH" "s3-arch.auth.$_NAME"
					return $?
				fi
			else
				echo "No s3-arch settings can be found in env" >&2
			fi
			;;
		use)
			_NAME=$2
			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi

			_kstoreinit || return 1

			_URL=$( kstore get "kcontext" "s3-arch.bucket.$_NAME" 2> /dev/null )
			if [ $? -ne 0 ]; then
				echo "No such context: $_NAME" >&2
				return 1
			fi

			_AUTH=$( kstore get "kcontext" "s3-arch.auth.$_NAME" 2> /dev/null )
			if [ $? -ne 0 ]; then
				echo "No such context: $_NAME" >&2
				return 1
			fi

			export ARCH_S3_BUCKET_URL=$_URL
			export ARCH_S3_AUTH=$_AUTH
			;;
		del)
			_NAME=$2
			if [ -z "$_NAME" ]; then
				echo "Please specify a context name" >&2
				return 1
			fi
			kstore get "kcontext" "s3-arch.bucket.$_NAME" 2> /dev/null > /dev/null
			if [ $? -eq 0 ]; then
				read -p "Delete context \"$_NAME\"? (y/n): " _CONFIRM
				if [ "$_CONFIRM" != "y" ]; then
					return 0
				fi
				kstore query "DELETE FROM $_KSTORE_TABLE WHERE key = 'kcontext' AND prop = 's3-arch.bucket.$_NAME'"
				kstore query "DELETE FROM $_KSTORE_TABLE WHERE key = 'kcontext' AND prop = 's3-arch.auth.$_NAME'"
				return $?
			else
				echo "No such context: $_NAME" >&2
			fi
			;;
		*)
			__func_head "list"
			__func_help "save NAME"
			__func_help "use NAME"
			__func_help "del NAME"
			;;
	esac
	return 1
}
