#!/bin/bash
#########################################################
# 							#
# This is BashStyle-NG  				#
#							#
# Licensed under GNU GENERAL PUBLIC LICENSE v3    	#
#							#
# Copyright Christopher Bratusek			#
#							#
#########################################################

. gettext.sh
export TEXTDOMAIN="bashstyle-rc"

is_number () {
	[[ ${1} =~ ^[+-]?[0-9]+([.,][0-9]+)?$ || \
		$((16#${1})) || \
		$((8#${1})) ]] 2>/dev/null \
		&& return 0 || return 1
}

is_int () {
	[[ ${1} =~ ^[+-]?[0-9]+$ ]] && return 0 || return 1
}

is_float () {
	[[ ${1} =~ ^[+-]?[0-9]+([.,][0-9]+)?$ ]] && return 0 || return 1
}

is_hex () {
	((16#${1})) 2>/dev/null && return 0 || return 1
}

is_octal () {
	((8#${1})) 2>/dev/null && return 0 || return 1
}

is_string () {
	! is_number "${1}" && return 0 || return 1
}

is_special () {
	[[ ! "${1}" =~ .*[[:xdigit:]].* ]] && return 0 || return 1
}

contains () {
	[[ "${1}" =~ .*${2}.* ]] && return 0 || return 1
}

starts_with () {
	[[ "${1}" =~ ^${2}.* ]] && return 0 || return 1
}

ends_with () {
	[[ "${1}" =~ .*${2}$ ]] && return 0 || return 1
}

is_hexcolor () {
	[[ "${1}" =~ ^[#]?([A-Fa-f0-9]{3}){1,2}$ ]] && return 0 || return 1
}

is_bool () {
	case ${1} in
		true | True | TRUE | false | False | FALSE | 0 | 1 ) return 0 ;;
		*                                                  ) return 1 ;;
	esac
}

is_true () {
	case ${1} in
		true | True | TRUE | 0 ) return 0 ;;
		*                      ) return 1 ;;
	esac
}

is_false () {
	case ${1} in
		false | False | FALSE | 1 ) return 0 ;;
		*                         ) return 1 ;;
	esac
}

###
#
# original version of the following:
#
# https://stackoverflow.com/questions/2138701/checking-correctness-of-an-email-address-with-a-regular-expression-in-bash/22689807#22689807
#
###

is_valid_address () {
	local regex="^[a-z0-9!#\$%&'*+/=?^_\`{|}~-]+(\.[a-z0-9!#$%&'*+/=?^_\`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z0-9]([a-z0-9-]*[a-z0-9])?\$"
	[[ "${1}" =~ ${regex} ]] && return 0 || return 1
}

is_valid_domain () {
	dig "${1}" | grep "ANSWER: 1" 1>/dev/null && return 0 || return 1
}

is_mail () {
	local address="${1}"
	local domain="$(echo "${1}" | gawk -F@ '{print $2}')"
	local status=0

	if ! is_valid_address "${address}"; then
		echo "$(eval_gettext "invalid address: ${address}")"
		status=1
	else
		if ! is_valid_domain "${domain}"; then
			echo "$(eval_gettext "domain: ${domain} unreachable")"
			status=1
		fi
	fi

	return ${status}
}

prog_exists () {
	local dependency="${1}"
	local program="${2}"
	local dep_return=1

	for dir in ${PATH//:/ }; do
		if [ -x "${dir}/${1}" ]; then
			dep_return=0
			continue 2
		fi
	done

	case ${dep_return} in
		0) return 0 ;;
		1) echo "$(eval_gettext "${dependency} not found, ${program} will not work.")"
		   return 1 ;;
	esac
}

case ${1} in
	n)	is_number "${2}"		;;
	i)	is_int "${2}"			;;
	f)	is_float "${2}"			;;
	h)	is_hex "${2}"			;;
	o)	is_octal "${2}"			;;
	hc)	is_hexcolor "${2}"		;;
	s)	is_string "${2}"		;;
	p)	is_special "${2}"		;;
	c)	contains "${2}" "${3}"		;;
	sw)	starts_with "${2}" "${3}"	;;
	ew)	ends_with "${2}" "${3}"		;;
	b)	is_bool "${2}"			;;
	bt)	is_true "${2}"			;;
	bf)	is_false "${2}"			;;
	P)	prog_exists "${2}" "${3}"	;;

	m)	check P "dig" "'check m'" && is_mail "${2}"	;;

	*)
		bashstyle-help -a "Christopher Roy Bratusek" -e "nano@jpberlin.de" -h "https://www.nanolx.org/"\
				-l "GNU GPL v3" -n "check" -s "$(eval_gettext "additional test functions")"\
				-v "${BSNG_VERSION}" -y "${BSNG_YEAR}"\
				-o "$(eval_gettext "n:4 [4[,.]4]|check if arg is any number")"\
				-o "$(eval_gettext "i:4|check if arg is integer")"\
				-o "$(eval_gettext "f:4[,.]4|check if arg is float")"\
				-o "$(eval_gettext "h:301DE8|check if arg is hex")"\
				-o "$(eval_gettext "o:24|check if arg is octal")"\
				-o "$(eval_gettext "hc:[#]FFFFFF|check if arg is valid hex color")"\
				-o "$(eval_gettext "s:test|check if arg is a string")"\
				-o "$(eval_gettext "p:+|check if arg is special character")"\
				-o "$(eval_gettext "c:testabc abc|check if arg1 contains arg2")"\
				-o "$(eval_gettext "sw:testabc t|check if arg1 starts with arg2")"\
				-o "$(eval_gettext "ew:14235 235|check if arg1 ends with arg2")"\
				-o "$(eval_gettext "b:\${VAR}|check if arg is a boolean")"\
				-o "$(eval_gettext "bt:\${VAR}|check if arg is boolean true")"\
				-o "$(eval_gettext "bf:\${VAR}|check if arg is boolean false")"\
				-o "$(eval_gettext "P:dep prog|check if dependency of program exists")"\
				-o "$(eval_gettext "m:test@dom.tld|check if arg is valid mail address")"
	;;
esac
