#!/bin/sh

. /usr/share/libubox/jshn.sh
. /lib/functions.sh

HOST_LIST=""

get_service_state() {
	client_sec="${1}"

	service_name=$(uci -q get ddnsmngr.${client_sec}.service_name)
	if [ -z "${service_name}" ]; then
		echo "0"
		return
	fi

	service_sec=$(uci -q show ddnsmngr | grep "service=\'${service_name}\'" | cut -d'.' -f 2 | head -1)
	if [ -z "${service_sec}" ]; then
		echo "0"
		return
	fi

	enabled=$(uci -q get ddnsmngr.${service_sec}.enabled)

	echo "${enabled}"
	return
}

get_hostname_status() {
	host_section="${1}"

	enabled=$(uci -q get ddnsmngr.${host_section}.enabled)
	if [ -z "${enabled}" ] || [ "${enabled}" = "0" ]; then
		state="Disabled"
	else
		# Check client is enabled or not
		client_sec=$(uci -q get ddnsmngr.${host_section}.dm_parent)
		if [ -z "${client_sec}" ]; then
			echo "Error"
			return
		fi

		client_enabled=$(uci -q get ddnsmngr.${client_sec}.enabled)
		if [ -z "${client_enabled}" ] || [ "${client_enabled}" = "0" ]; then
			echo "Disabled"
			return
		fi

		service_enabled=$(get_service_state ${client_sec})
		if [ "${service_enabled}" = "0" ]; then
			echo "Disabled"
			return
		fi

		log_dir=$(uci -q get ddnsmngr.global.ddns_logdir)
		if [ -z "${log_dir}" ]; then
			log_dir="/var/log/ddnsmngr"
		fi

		log_file="${log_dir}/${host_section}.log"
		if [ -f "${log_file}" ]; then
			state="Registered"
			while read -r line; do
				if [[ "${line}" =~ "Registered IP" ]] || [[ "${line}" =~ "Update successful" ]]; then
					state="Registered"
				elif [[ "${line}" =~ "Update needed" ]]; then
					state="UpdateNeeded"
				elif [[ "${line}" =~ "NO valid IP found" ]]; then
					state="Error"
				elif [[ "${line}" =~ "Get registered/public IP for" ]] && [[ "${line}" =~ "failed" ]]; then
					state="Error"
				elif [[ "${line}" =~ "Host section not configured correctly" ]]; then
					state="Error"
				fi
			done < "${log_file}"
		else
			state="Error"
		fi
	fi

	echo "${state}"
}

select_host() {
	host_sec="${1}"
	client_sec="${2}"

	config_get client_section "${host_sec}" dm_parent ""
	if [ "${client_sec}" != "${client_section}" ]; then
		return
	fi

	config_get_bool enabled "${host_sec}" enabled 0
	if [ "${enabled}" -eq 0 ]; then
		return
	fi

	HOST_LIST="${HOST_LIST} ${host_sec}"
}

get_enabled_hostnames() {
	client_section="${1}"
	HOST_LIST=""

	config_load ddnsmngr
	config_foreach select_host host ${1}

	echo "${HOST_LIST}"
}

get_client_status() {
	client_section="${1}"

	enabled=$(uci -q get ddnsmngr.${client_section}.enabled)
	if [ -z "${enabled}" ] || [ "${enabled}" = "0" ]; then
		state="Disabled"
	else
		service_enabled=$(get_service_state "${client_section}")
		if [ "${service_enabled}" = "0" ]; then
			echo "Error_Misconfigured"
			return
		fi

		# if any of the host status is ERROR set status to Error, otherwise status equivalent to last enabled hostname status
		hosts_list=$(get_enabled_hostnames "${client_section}")
		if [ -z "${hosts_list}" ]; then
			# no hostname configured or all are disabled
			state="Error_Misconfigured"
		else
			for host in $hosts_list; do
				last_host="${host}"
				host_state=$(get_hostname_status "${host}")
				if [ "${host_state}" = "Error" ]; then
					break;
				fi
			done

			log_dir=$(uci -q get ddnsmngr.global.ddns_logdir)
			if [ -z "${log_dir}" ]; then
				log_dir="/var/log/ddnsmngr"
			fi

			log_file="${log_dir}/${last_host}.log"
			if [ -f "${log_file}" ]; then
				state="Connecting"
				while read -r line; do
					if [[ "${line}" =~ "Update successful" ]] || [[ "${line}" =~ "No update needed" ]]; then
						state="Updated"
					elif [[ "${line}" =~ "ERROR" ]] && [[ "${line}" =~ "Please check your configuration" ]]; then
						state="Error_Misconfigured"
					elif [[ "${line}" =~ "Registered IP" ]]; then
						state="Connecting"
					elif [[ "${line}" =~ "ERROR" ]] || [[ "${line}" =~ "failed" ]]; then
						state="Error"
					fi
				done < "${log_file}"
			else
				state="Error"
			fi
		fi
	fi

	echo "${state}"
}

get_last_error() {
	client_section="${1}"

	enabled=$(uci -q get ddnsmngr.${client_section}.enabled)
	if [ -z "${enabled}" ] || [ "${enabled}" = "0" ]; then
		error="NO_ERROR"
	else
		service_enabled=$(get_service_state "${client_section}")
		if [ "${service_enabled}" = "0" ]; then
			echo "MISCONFIGURATION_ERROR"
			return
		fi

		# if any of the host status is ERROR set status to Error, otherwise status equivalent to last enabled hostname status
		hosts_list=$(get_enabled_hostnames "${client_section}")
		if [ -z "${hosts_list}" ]; then
			# no hostname configured or all are disabled
			error="MISCONFIGURATION_ERROR"
		else
			for host in $hosts_list; do
				last_host="${host}"
				host_state=$(get_hostname_status "${host}")
				if [ "${host_state}" = "Error" ]; then
					break;
				fi
			done

			log_dir=$(uci -q get ddnsmngr.global.ddns_logdir)
			if [ -z "${log_dir}" ]; then
				log_dir="/var/log/ddnsmngr"
			fi

			log_file="${log_dir}/${last_host}.log"
			if [ -f "${log_file}" ]; then
				error="NO_ERROR"
				while read -r line; do
					if [[ "${line}" =~ "ERROR" ]] && [[ "${line}" =~ "Please check your configuration" ]]; then
						error="MISCONFIGURATION_ERROR"
					elif [[ "${line}" =~ "NO valid IP found" ]]; then
						error="DNS_ERROR"
					elif [[ "${line}" =~ "Get registered/public IP for" ]] && [[ "${line}" =~ "failed" ]]; then
						error="DNS_ERROR"
					elif [[ "${line}" =~ "Authentication Failed" ]]; then
						error="AUTHENTICATION_ERROR"
					elif [[ "${line}" =~ "Transfer failed" ]]; then
						error="CONNECTION_ERROR"
					elif [[ "${line}" =~ "WARN" ]] && [[ "${line}" =~ "failed" ]]; then
						error="CONNECTION_ERROR"
					elif [[ "${line}" =~ "Registered IP" ]] || [[ "${line}" =~ "Update successful" ]]; then
						error="NO_ERROR"
					fi
				done < "${log_file}"
			else
				error="MISCONFIGURATION_ERROR"
			fi
		fi
	fi

	echo "${error}"
}

case "$1" in
	list)
		echo '{ "last_update" : {"host":"string"}, "host_status" : {"host":"string"}, "client_status" : {"client":"string"}, "last_error" : {"client":"string"}, "agent_info" : {} }'
	;;
	call)
		case "$2" in
			last_update)
				read -r input
				json_load "${input}"
				json_get_var host_section "host"
				json_cleanup

				last_update="0001-01-01T00:00:00Z"

				if [ -z "${host_section}" ]; then
					json_init
					json_add_string "last_update" "${last_update}"
					json_dump
					exit 0
				fi

				run_dir=$(uci -q get ddnsmngr.global.ddns_rundir)

				if [ -z "${run_dir}" ]; then
					run_dir="/var/run/ddnsmngr"
				fi

				file_path="${run_dir}/${host_section}.update"
				last_time=$(cat "${file_path}")
				if [ -z "${last_time}" ]; then
					json_init
					json_add_string "last_update" "${last_update}"
					json_dump
					exit 0
				else
					# strip next line from end
					last_time=$(echo -e $last_time | tr -d '\n')
				fi

				up_time=$(cat /proc/uptime | cut -d' ' -f1 | cut -d'.' -f1)
				cur_time=$(date '+%s')

				epoch_time=$(( cur_time - up_time + last_time ))

				last_update=$(date -d @"${epoch_time}" +'%Y-%m-%dT%H:%M:%SZ')

				json_init
				json_add_string "last_update" "${last_update}"
				json_dump
			;;
			host_status)
				read -r input
				json_load "${input}"
				json_get_var host_section "host"
				json_cleanup

				if [ -z "${host_section}" ]; then
					json_init
					json_add_string "status" "Error"
					json_dump
					exit 0
				fi

				state=$(get_hostname_status "${host_section}")

				json_init
				json_add_string "status" "${state}"
				json_dump
			;;
			client_status)
				read -r input
				json_load "${input}"
				json_get_var client_section "client"
				json_cleanup

				if [ -z "${client_section}" ]; then
					json_init
					json_add_string "status" "Error"
					json_dump
					exit 0
				fi

				state=$(get_client_status "${client_section}")

				json_init
				json_add_string "status" "${state}"
				json_dump
			;;
			last_error)
				read -r input
				json_load "${input}"
				json_get_var client_section "client"
				json_cleanup

				if [ -z "${client_section}" ]; then
					json_init
					json_add_string "last_error" "CONNECTION_ERROR"
					json_dump
					exit 0
				fi

				error=$(get_last_error "${client_section}")

				json_init
				json_add_string "last_error" "${error}"
				json_dump
			;;
			agent_info)
				ver=$(curl -V | awk '{print $2}' | head -1)
				user_agent="curl/${ver}"

				json_init
				json_add_string "backend" "ddns-script"
				json_add_string "user_agent" "${user_agent}"
				json_dump
			;;
		esac
	;;
esac
