#!/usr/bin/env bash


#
# Copyright (C) 2016-2020  Hiveon
# Distributed under GNU GENERAL PUBLIC LICENSE 2.0
# License information can be found in the LICENSE file or at https://github.com/minershive/hiveos-asic/blob/master/LICENSE.txt
#


declare -r ant_functions_lib_mission='Antminer and Hiveon functions'
declare -r ant_functions_lib_version='0.1.6'


# !!! bash strict mode, no unbound variables

#set -o nounset # !!! this is a library, so we don't want to break the other's scripts


#
# functions: script infrastructure
#

#base
function print_script_version {
	echo -e "${YELLOW-}${script_mission}, version ${script_version}${NOCOLOR-}"
	echo
}

function errcho {
	#
	# Usage: errcho [arg...]
	#
	# uniform error logging to stderr
	#

	echo -e -n "${BRED-}$0"
	for (( i=${#FUNCNAME[@]} - 2; i >= 1; i-- )); { echo -e -n "${RED-}:${BRED-}${FUNCNAME[i]}"; }
	echo -e " error:${NOCOLOR-} $*"

} 1>&2

#
# functions: audit
#
# we need to audit externally--does the script work as intended or not (like the system returns exitcode "file not found")
# [[ $( script_to_audit ) != 'I AM FINE' ]] && echo "Something wrong with $script_to_check"
#

function print_i_am_doing_fine_then_exit {
	#
	# Usage: print_i_am_fine_and_exit
	#

	# code

	echo "$__audit_ok_string"
	exit $(( exitcode_OK ))
}

#base
function is_function_exist {
	#
	# Usage: is_function_exist 'function_name'
	#
	# stdin: none
	# stdout: none
	# exit code: boolean
	#

	# args

	(( $# != 1 )) && { errcho 'invalid number of arguments'; return $(( exitcode_ERROR_IN_ARGUMENTS )); }
	local -r function_name="$1"

	# code

	declare -F -- "$function_name" >/dev/null
}

#base
function __list_functions {
	#
	# List all functions but started with '_'
	#

	# consts

	local -r private_function_attribute_RE='^_'

	# vars

	local function_name=''
	local -a all_functions=()
	local -a private_functions=()
	local -a public_functions=()

	# code

	all_functions=( $( compgen -A function ) )

	for function_name in "${all_functions[@]}"; do
		if [[ "${function_name}" =~ $private_function_attribute_RE ]]; then
			private_functions+=("$function_name")
		else
			public_functions+=("$function_name")
		fi
	done

	if (( ${#private_functions[@]} != 0 )); then
		echo "${#private_functions[@]} private function(s):"
		echo
		printf '%s\n' "${private_functions[@]}"
		echo
	fi

	echo "${#public_functions[@]} public function(s):"
	echo
	printf '%s\n' "${public_functions[@]}"
	echo
}


#ant functions

function is_hiveon_fw_signed {

	# consts

	local -r upgrade_script='/www/pages/cgi-bin/upgrade.cgi'
	local -r uncommented_openssl_RE='^[[:space:]]*openssl'

	# vars

	local -i is_certs_exist=0
	local first_match

	# code

	for first_match in /etc/*.pem; do
		[ -s "$first_match" ] && is_certs_exist=1
		break
	done

	(( is_certs_exist )) && [[ -s "$upgrade_script" ]] && grep -Eqe "$uncommented_openssl_RE" -- "$upgrade_script"
}

#get status
function hiveon_status {
	#
	# Usage: hiveon_status '{JSON}'
	#
	(( $# > 1 )) && { errcho 'invalid number of arguments'; return $(( exitcode_ERROR_IN_ARGUMENTS )); }
	local -r input_text="${1:-$( < /dev/stdin )}" # get from arg or stdin

	system_status=$(jq -r '.[0].Type' <<< "$input_text")

	if [[ -n $system_status ]]; then
		if grep -v 'S9 6-boards' <<< "$system_status" | grep -Fq '('; then #)'# syntax highlighting fix
			system_status="$( echo "$system_status" | grep '(' | sed 's/.*(\|).*//g' )"
		else
			system_status='mining'
		fi
	fi

	#Hiveon before 17 series
	if [[ $system_status == 'mining' && -n "$HIVEON_VERSION" ]]; then
		local tune_board=0
		local tune_chip=0
		if [ -e /www/pages/cgi-bin/check-auto-tune-running.cgi ]; then
			tune_board=$(sh /www/pages/cgi-bin/check-auto-tune-running.cgi)
		fi
		if [ -e /www/pages/cgi-bin/check-auto-chip-tune-running.cgi ]; then
			tune_chip=$(sh /www/pages/cgi-bin/check-auto-tune-running.cgi)
		fi

		#L3 without check-auto-tune-running.cgi
		if [[ $ASIC_MODEL =~ 'Antminer L3' ]]; then
			if ps w | grep -q '[a]uto-tune'; then
				tune_board=1
			else
				tune_board=0
			fi
		fi

		if [[ $tune_board -eq 1 || $tune_chip -eq 1 ]]; then
			system_status='tuning'
		fi
	fi
	echo $system_status
}

#get voltage
function hiveon_voltage {
	#
	# Usage: hiveon_voltage '[...,0,0,X,X,X,0,...]'
	#
	# If the API does not return voltage
	# Example acn=[0,0,0,0,0,63,63,63,0,0,0,0,0,0,0,0]
	#

	(( $# > 1 )) && { errcho 'invalid number of arguments'; return $(( exitcode_ERROR_IN_ARGUMENTS )); }
	local -r input_text="${1:-$( < /dev/stdin )}" # get from arg or stdin

	voltage_list="[]"
	if [ -e /www/pages/cgi-bin/get_adv_config.cgi ]; then
		voltage_mask=$(echo "$input_text" | jq '. | to_entries | .[].value | if . > 0 then 1 else 0 end')
		voltage_list_pre=($(sh /www/pages/cgi-bin/get_adv_config.cgi | grep bitmain-voltage | awk -F\= '{print $2/100}'))
		n=0
		declare -a format_list
		for chain in $voltage_mask; do
			if [ $chain == 1 ]; then
				chain=${voltage_list_pre[$n]}
				(( n++ ))
			fi
			format_list+=($chain)
		done
		voltage_list=$(echo ${format_list[@]} | jq -s '.')
	fi

	echo $voltage_list
}


source asic-model || echo 'ERROR: /hive/bin/asic-model not found'

# consts

declare -r __audit_ok_string='I AM DOING FINE'
# shellcheck disable=SC2034
declare -r -i exitcode_OK=0
declare -r -i exitcode_ERROR_NOT_FOUND=1
declare -r -i exitcode_ERROR_IN_ARGUMENTS=127
# shellcheck disable=SC2034
declare -r -i exitcode_ERROR_SOMETHING_WEIRD=255

declare -r -i exitcode_IS_EQUAL=0
declare -r -i exitcode_GREATER_THAN=1
declare -r -i exitcode_LESS_THAN=2

# main

if ! ( return 0 2>/dev/null ); then # not sourced

	declare -r script_mission="$ant_functions_lib_mission"
	declare -r script_version="$ant_functions_lib_version"

	case "$*" in
		'')
			source colors
			print_script_version
			__list_functions
			;;
		*)
			if is_function_exist "$1"; then
				"$@" # potentially unsafe
			else
				errcho "function '$1' is not defined"
			fi
			;;
	esac
fi
