#!/usr/bin/env bash

#[ -t 1 ] &&
. colors
[[ -f $RIG_CONF ]] && . $RIG_CONF

[[ $MAINTENANCE == 2 ]] &&
	echo -e "${YELLOW}Maintenance mode enabled, exiting${NOCOLOR}" &&
	exit 1

# set timeout for fan test
timeout=15

# use for testing without applying anything
DEBUG=0


as=0
mn=0


amd_set_fan_pwm() {
	local hwmondir="$1"
	local fanpwm="$2"
	[[ ! -e "$hwmondir" ]] && return
	echo 1 > ${hwmondir}/pwm1_enable
	echo "$fanpwm" > ${hwmondir}/pwm1 2>/dev/null && return
	# try higher value
	[[ $fanpwm -eq 0 ]] && echo "4" > ${hwmondir}/pwm1
	return
}


stop_fans() {
	if [[ ! -z ${NVIDIA_BUSID[*]} ]]; then
		echo -e "${CYAN}> Stopping all NVIDIA GPU fans...${NOCOLOR}"
		local args=" --setlogo 0 --setfan 1"
		# apply nvidia-settings
		[[ "$DEBUG" == "1" ]] && echo "$args" ||
			nvtool -q --nodev $args >/dev/null
	fi

	if [[ ! -z ${AMD_BUSID[*]} ]]; then
		echo -e "${CYAN}> Stopping all AMD GPU fans...${NOCOLOR}"
		for busid in "${AMD_BUSID[@]}"; do
			# find gpu_id by bus_id and apply fan setting to gpu
			cardno=${AMD_CARDID["$busid"]}
			hwmondir=`realpath /sys/class/drm/card${cardno}/device/hwmon/hwmon*/ 2>&1`
			[[ $? -ne 0 ]] && echo -e "${RED}Setting GPU with busid $busid failed${NOCOLOR}" && return

			[[ "$DEBUG" == "1" ]] &&
				echo "-i $cardno --set-fanspeed 0" &&
				continue

			echo "auto" > /sys/class/drm/card$cardno/device/power_dpm_force_performance_level
			amd_set_fan_pwm "$hwmondir" 0
		done
	fi

	echo -e "${CYAN}> Checking fans speed...${NOCOLOR}"
	sleep 10
	stats=`gpu-stats`
	fans=(`echo "$stats" | jq -r ".fan | .[]" 2>/dev/null`)
	busids=(`echo "$stats" | jq -r ".busids | .[]" 2>/dev/null`)
	i=0
	for key in "${GPU_KEYS[@]}"; do
		[[ ${fans[$key]} -ne 0 ]] && echo -e "${YELLOW}GPU#$i with busid ${busids[$key]} still spins fans - ${fans[$key]}%${NOCOLOR}"
		((i++))
	done
}


test_gpu() {
	# convert to gpu-detect.json index
	index=${GPU_KEYS[$1]}
	[[ -z $index ]] && echo -e "${RED}GPU #$1 not found${NOCOLOR}" && return

	gpudata=`echo "$gpu_detect_json" | jq '.['$index']'`
	busid=`echo "$gpudata" | jq -r .busid`
	name=`echo "$gpudata" | jq -r .name`
	brand=`echo "$gpudata" | jq -r .brand`

	local COLOR=$YELLOW
	[[ $brand == "nvidia" ]] && COLOR=$GREEN
	[[ $brand == "amd" ]] && COLOR=$RED
	[[ $brand == "cpu" ]] && return

	echo -ne "> Spinning fans on GPU ${YELLOW}#$1${NOCOLOR} $busid ${COLOR}$name${NOCOLOR}"
	[[ "$DEBUG" == "1" ]] && echo ""

	if [[ $brand == "nvidia" ]]; then
		local gpu_idx=0
		# find gpu index by bus_id
		for id in "${NVIDIA_BUSID[@]}"; do
			[[ $busid == $id ]] && break
			((gpu_idx++))
		done
		# apply fan setting to 100%
		args=" -i $gpu_idx --setfan 100 --setlogo 100"
		[[ "$DEBUG" == "1" ]] && echo "$args" ||
			nvtool -q --nodev $args >/dev/null
		# sleep for (timeout) in sec
		for (( i=0; i < timeout; i++ )); do
			echo -n "." && sleep 1
		done
		# set fan speed to 0% again
		args=" -i $gpu_idx --setfan 1 --setlogo 0"
		[[ "$DEBUG" == "1" ]] && echo "$args" ||
			nvtool -q --nodev $args >/dev/null
		echo -e "${GREEN}OK${NOCOLOR}"
		sleep 1
	fi

	if [[ $brand == "amd" ]]; then
		# find gpu index by bus_id
		cardno=${AMD_CARDID["$busid"]}
		hwmondir=`realpath /sys/class/drm/card${cardno}/device/hwmon/hwmon*/ 2>&1`
		[[ $? -ne 0 ]] && echo -e "${RED}Setting GPU with busid $busid failed${NOCOLOR}" && return
		[[ -e ${hwmondir}/pwm1_max ]] && fanmax=`head -1 ${hwmondir}/pwm1_max 2>/dev/null` || fanmax=255
		[[ "$fanmax" -eq 0 ]] && echo -e "${RED}Setting GPU with busid $busid failed (Max fan is unknown)${NOCOLOR}" && return
		# apply fan setting to 100%
		[[ "$DEBUG" == "1" ]] && echo "-i $cardno --set-fanspeed 100" ||
			amd_set_fan_pwm "$hwmondir" "$fanmax"
		# sleep for(timeout) in sec
		for ((i=0; i<$timeout; i++)); do
			echo -n "." && sleep 1
		done
		# set fan speed to 0% again
		[[ "$DEBUG" == "1" ]] && echo "-i $cardno --set-fanspeed 0" ||
			amd_set_fan_pwm "$hwmondir" 0
		echo -e "${GREEN}OK${NOCOLOR}"
		sleep 1
	fi
}

if [ ! -f $GPU_DETECT_JSON ]; then
	gpu_detect_json=`gpu-detect listjson`
else
	gpu_detect_json=`cat $GPU_DETECT_JSON`
fi


declare -a NVIDIA_BUSID=(`echo "$gpu_detect_json" | jq -r '. | to_entries[] | select(.value.brand == "nvidia") | .value.busid'`)
declare -a NVIDIA_FANS=(`echo "$gpu_detect_json" | jq -r '. | to_entries[] | select(.value.brand == "nvidia") | .value.fan_cnt'`)
declare -a AMD_BUSID=(`echo "$gpu_detect_json" | jq -r '. | to_entries[] | select(.value.brand == "amd") | .value.busid'`)
declare -A AMD_CARDID
dirs=`ls -d1 /sys/class/drm/card*/device/pp_table 2>/dev/null | sort --version-sort` #natural sort for 10+ cards
if [[ ! -z $dirs ]]; then
	for dir in $dirs; do
		busid=`cat ${dir%/*}/uevent | grep PCI_SLOT_NAME | awk -F= '{print substr($2,6)}'`
		[[ $dir =~ \/card([0-9a-z]+)\/ ]]
		AMD_CARDID["$busid"]=${BASH_REMATCH[1]}
		#echo "$busid = ${BASH_REMATCH[1]}"
	done
fi

# indexes of valid gpus
declare -a GPU_KEYS=(`echo "$gpu_detect_json" | jq -r '. | to_entries[] | select(.value.brand != "cpu") | .key'`)

gpu_count=${#GPU_KEYS[*]}

if [[ "$DEBUG" == "1" ]]; then
	echo "NVIDIA: ${NVIDIA_BUSID[*]}"
	echo "NVFANS: ${NVIDIA_FANS[*]}"
	echo "AMD:    ${AMD_BUSID[*]}"
	echo "KEYS:   ${GPU_KEYS[*]}"
	echo "COUNT:  ${#GPU_KEYS[*]}"
fi

date

echo -e "${WHITE}=================== START SEARCH GPU ===================${NOCOLOR}"
gpu-detect list
echo ""

[[ -z ${NVIDIA_BUSID[*]} && -z ${AMD_BUSID[*]} ]] &&
	echo -e "No ${RED}AMD${NOCOLOR} or ${GREEN}NVIDIA${NOCOLOR} found" &&
	exit 1

[[ ! -z $1 ]] && [[ -z "${1##*[!0-9]*}" || $1 -ge $gpu_count ]] &&
	echo -e "${YELLOW}GPU index must be in range [0-$gpu_count]${NOCOLOR}" &&
	exit 1



if [[ "$DEBUG" != "1" ]]; then
	as=$(screen -ls | grep -c autoswitch)

	if miner status >/dev/null; then
		echo "> Stopping miner session"
		miner stop
		mn=1
	fi

	echo "> Stopping autofan"
	autofan stop
fi 

echo "> Stopping Fans"
[[ ! -z ${AMD_BUSID[*]} ]] && echo -e "${YELLOW}Notice: If you have AMD GPU with GPU temp 511 this fan will not be stopped!${NOCOLOR}"
stop_fans

# onboard and not properly detected gpus have NO index
if [[ -z $1 ]]; then
	gpuid=0
	while [[ $gpuid -lt $gpu_count ]]; do
		#echo -e $gpuid
		test_gpu $gpuid
		let gpuid=gpuid+1
	done
else
	gpuid=$1
	test_gpu $gpuid
fi


if [[ "$DEBUG" != "1" ]]; then
	echo -e "${CYAN}> Restoring OC settings...${NOCOLOR}"
	[[ ! -z ${NVIDIA_BUSID[*]} ]] && nvidia-oc 1>/dev/null
	[[ ! -z ${AMD_BUSID[*]} ]] && amd-oc 1>/dev/null
	[[ ! -z ${INTEL_BUSID[*]} ]] && intel-oc 1>/dev/null

	echo "> Starting autofan"
	autofan start

	#echo -e "> Starting hashrate watchdog"
	#wd start

	[[ $mn -ne 0 ]] && 
		echo "> Starting miner session" &&
		miner start

	[[ $as -ne 0 ]] && nohup bash -c 'sleep 15 && autoswitch start' > /dev/null 2>&1 &
fi

exit 0
