#!/usr/bin/env bash
# __    __         __                  _                                            _                      _
#/ / /\ \ \___    /__\ ___  __ _ _   _(_)_ __ ___     /\/\   ___  _ __ ___    /\/\ (_)_ __   ___ _ __ __ _| |___
#\ \/  \/ / _ \  / \/// _ \/ _\`| | | | | '__/ _ \   /    \ / _ \| '__/ _ \  /    \| | '_ \ / _ \ '__/ _\`| / __|
# \  /\  /  __/ / _  \  __/ (_| | |_| | | | |  __/  / /\/\ \ (_) | | |  __/ / /\/\ \ | | | |  __/ | | (_| | \__ \
#  \/  \/ \___| \/ \_/\___|\__, |\__,_|_|_|  \___|  \/    \/\___/|_|  \___| \/    \/_|_| |_|\___|_|  \__,_|_|___/
#                             |_|

# do not allow to run it interactively
[[ -t 0 ]] && exit 0

source /etc/environment
export $(cat /etc/environment | grep -vE '^$|^#' | cut -d= -f1) #export all variables from file
#export PATH
#export CUDA_DEVICE_ORDER
export HOME=/home/user #required by ccminer

# make directory in RAM
mkdir -p /run/hive > /dev/null 2>&1

# prevent Nvidia driver loading by nvidia tools in ssh connection
touch /run/hive/NV_OFF

#[ -t 1 ] &&
source colors # use them anyway
[[ -e /etc/brand.conf ]] && source /etc/brand.conf
[[ -z $BRAND ]] && BRAND="Hive"

# Check diskless
DISKLESS=0
[[ -f /hive-config/.DISKLESS_AMD && $(cat /proc/mounts | grep "/ " | awk '{print $1}') == tmpfs ]] && DISKLESS=1

# Check benchmark
bench=0
benchmark check > /dev/null 2>&1
[[ $? == 0 ]] && bench=1 || bench=0


function echo2 {
        if [[ $HIDDEN_MODE_ENABLE ]]; then
           return
        fi
	echo -e "$1" > /dev/tty1
	echo -e "$1" | sed 's/\x1b\[[0-9;]*m//g' # remove colors from syslog
}


cat /proc/mounts | grep -q /hive-config
if [[ $? -ne 0 && ! -f $RIG_CONF && $DISKLESS != 1 ]]; then
	#0 - mounted (grep ok), 1 - grep not found (unmounted)
	#checking for rig.conf is for very old systems without a mounted config partition
	echo2 "${RED}Config directory /hive-config is not mounted, please check filesystem.${NOCOLOR}"
	echo2 "${RED}This needs to be fixed for proper system operation.${NOCOLOR}"
	echo2 "${YELLOW}Alt+F2 to switch to other terminal and login.${NOCOLOR}"

	#nohup sudo -i bash > /dev/null 2>&1 &
	#systemctl restart hive-console

	exit 1
fi


# update from root
[[ $DISKLESS != 1 && ! -z $RIG_CONF && ! -f $RIG_CONF && -f /${RIG_CONF##*/} ]] && mv /${RIG_CONF##*/} $RIG_CONF

# load config
if [[ -f $RIG_CONF ]]; then
	# ensure we have unix config
	dos2unix-safe $RIG_CONF
	source $RIG_CONF
	# update user
	hive-passwd updateuser
fi


[[ -f /hive-config/ref_id.txt ]] && dos2unix-safe /hive-config/ref_id.txt


if [[ -e /hive-config/branding-logo.txt ]]; then
	BRANDING_LOGO=$(cat /hive-config/branding-logo.txt; echo .) #echo . to preserve new lines
	BRANDING_LOGO=${BRANDING_LOGO%.} #remove last .
elif [[ -z $BRANDING_LOGO ]]; then
	BRANDING_LOGO="${BYELLOW}
_______ _______ ___ ___ _______
|   |   |_     _|   |   |    ___|
|       |_|   |_|   |   |    ___|
|___|___|_______|\_____/|_______|
${NOCOLOR}
"
fi


#Check for proxy var. Or agent and others started from here will not see it
source http_proxy.sh


#Make directory for miners logs in /var/log/miner
#miner logdirscreate


export GPU_COUNT_AMD=`gpu-detect AMD`
export GPU_COUNT_NVIDIA=`gpu-detect NVIDIA`
export GPU_COUNT_INTEL=`gpu-detect INTEL`
export GPU_FIRST_AMD=`gpu-detect AMD_FIRST`
export GPU_FIRST_NVIDIA=`gpu-detect NVIDIA_FIRST`

#cd $(dirname $(realpath $0))

SEP=" · "


sysinfo="$BPURPLE$(uname -sr)$NOCOLOR$SEP${BYELLOW}H $WHITE$(dpkg -s hive | grep -oP "^Version: \K.*$")$NOCOLOR"
sysinfo+="$SEP$BCYAN${WORKER_NAME:-$(hostname)}$NOCOLOR$SEP${WHITE}$(hostname -I)$NOCOLOR"

echo2 "$BRANDING_LOGO$sysinfo\n"

[[ $DISKLESS == 1 ]] && echo2 "\n${BGREEN}Diskless rig detected${NOCOLOR}\n\n"

#sleep 2

### VPN's #############################################################################################
# will wait for interface
openvpn-install
wireguard-install

### Check for internal GPU ##############################################################################

# rm config so maybe xorg autoconfig will work
#rm /etc/X11/xorg.conf > /dev/null 2>&1


#if [[ $GPU_FIRST_AMD == 0 && $GPU_FIRST_NVIDIA == 0 && $DISKLESS != 1 && $X_DISABLED != 1 ]]; then
#	echo2 "$YELLOW
##########################################################################
###
###  You have connected monitor to integrated GPU on the motherboard?
###  It's better to connect monitor to the 1st external GPU (in 16x slot).
###
##########################################################################
#$NOCOLOR"
#fi

### Nvidia not first warning ############################################################################
if [[ $GPU_FIRST_AMD -gt 0 && $GPU_COUNT_NVIDIA -gt 0 ]]; then     # not yet using $GPU_COUNT_INTEL -gt 0
	echo2 "$YELLOW
#####################################################################
###
###   WARNING
###
###   You have mix of NVIDIA and AMD cards.
###   AMD is detected to be in the first slot.
###   It's better to have NVIDIA in the 1st PCIe slot for OC to work.
###   X server will crash in this configuration.
###
#####################################################################
$NOCOLOR"
fi


# request maintenance mode before loading drivers
if [[ ! -z $RIG_ID && ! -z $RIG_PASSWD && ! -z $HIVE_HOST_URL ]]; then
	# check and waiting for online. rigs with ssd can boot faster than network is configured.
	# systemd-networkd-wait-online is broken on Ubuntu 18 image
	for((i=1; i<10; i++))
	do
		networkctl list | grep -q routable && break
		networkctl list | grep -q configuring || break
		echo2 "> Waiting for network ($i)"
		sleep 1
	done

	echo2 "> Quering boot settings"

	[[ $DISABLE_CERT_CHECK -ne 0 ]] && insecure="--insecure" || insecure=

	request=`jq -c -n --arg rig_id "$RIG_ID" --arg passwd "$RIG_PASSWD" '{"method":"get_options","params":{"rig_id": $rig_id,"passwd": $passwd}}' 2>/dev/null`
	response=`echo "$request" | curl $insecure -L --data @- --connect-timeout 7 --max-time 15 --silent -XPOST "$HIVE_HOST_URL/worker/api" -H "Content-Type: application/json"`
	exitcode=$?
	if [[ $exitcode -ne 0 ]]; then
		echo2 "${RED}ERROR: connection to API server ($HIVE_HOST_URL) failed ($exitcode)${NOCOLOR}"
	else
		PARAM_NAMES=("disable_gui" "maintenance_mode" "doh" "shellinabox_enable" "ssh_enable" "ssh_authorized_keys" "ssh_password_enable" "vnc_enable" "vnc_password")
		PARAM_VARS=("X_DISABLED" "MAINTENANCE" "DOH_ENABLED" "SHELLINABOX_ENABLE" "SSH_ENABLE" "SSH_AUTHORIZED_KEYS" "SSH_PASSWORD_ENABLE" "VNC_ENABLE" "VNC_PASSWORD")

		err_code=`echo "$response" | jq -r ".error.code" 2>/dev/null`
		err_message=`echo "$response" | jq -r ".error.message" 2>/dev/null`
		if [[ -z "$err_code" || "$err_code" != "null" ]]; then
			[[ ! -z $err_message && "$err_message" != "null" ]] &&
				echo2 "${RED}Got error ($err_code): $err_message${NOCOLOR}" ||
				echo2 "${RED}Got bad response: ${YELLOW}'$response'${NOCOLOR}"
		else
			# extract each field separately: a line-based readarray shifts all
			# values after a multi-line one (several ssh keys) onto wrong vars
			index=0
			for var in ${PARAM_VARS[@]}; do
				value=`echo "$response" | jq -r ".result.${PARAM_NAMES[index]} | if . == null then empty else . end" 2>/dev/null`
				# tolerate boolean json values
				[[ "$value" == "true" ]] && value=1
				[[ "$value" == "false" ]] && value=0
				if [[ "${!var}" != "$value" ]]; then
					# strip ssh keys
					[[ ${#value} -gt 20 ]] &&
					echo2 "$var=${value::20}..." ||
					echo2 "$var=$value"
				fi
				printf -v "$var" "%s" "$value"
				((index++))
			done
			# apply with new params
			(source remote-connections; apply_conf)
		fi
	fi
fi


if [[ $MAINTENANCE == 2 ]]; then
	echo2 "> Maintenance mode. ${YELLOW}WITHOUT GPU DRIVERS!${NOCOLOR}"
else
	[[ -e $BUSID_FILE ]] && source $BUSID_FILE

	# disable AMD APU (it is not always first)
	if [[ $BUSID_KEEP_APU == 0 ]]; then
		source /hive/etc/gpu.ids
		busid=`lspci | grep -E "$GPU_DETECT_STRING" | grep -E "$GPU_AMD_INTERNAL" | awk '{print $1}' | head -1`
		if [[ ! -z "$busid" && -e /sys/bus/pci/devices/0000:$busid/remove ]]; then
			gpu-detect listjson | jq '.[0].name |= sub("Radeon "; "")' > "${GPU_DETECT_JSON}.boot"
			echo2 "> Disabling AMD APU $busid"
			echo 1 > /sys/bus/pci/devices/0000:$busid/remove
		fi
	fi

	# Disable GPU audio. AMD does not like it
	if [[ $BUSID_DISABLE_AUDIO -eq 1 ]]; then
		for busid in $(lspci | grep "Audio" | grep "NVIDIA" | awk '{print $1}'); do
			echo2 "> Disabling Audio device $busid"
			echo 1 > /sys/bus/pci/devices/0000:$busid/remove
		done
	fi

	# Disable GPU by BUS ID
	if [[ ! -z $BUSID_DISABLE ]]; then
		[[ ! -e "${GPU_DETECT_JSON}.boot" ]] && gpu-detect listjson > "${GPU_DETECT_JSON}.boot"
		for busid in $BUSID_DISABLE; do
			busid=${busid,,} # use low case
			if [[ $busid =~ ^[0-9a-f]{2}$ ]]; then
				busid="$busid:00.0"
			elif [[ $busid =~ ^[0-9a-f]{2}:[0-9a-f]{2}$ ]]; then
				busid="$busid.0"
			fi
			[[ ! -e /sys/bus/pci/devices/0000:$busid/remove ]] && continue
			#message warn "Disabling GPU $busid"
			echo2 "> Disabling GPU $busid"
			echo 1 > /sys/bus/pci/devices/0000:$busid/remove
		done
	fi

	### modprobe drivers, nvidia better to be first ########################################
	if [[ $GPU_COUNT_NVIDIA -gt 0 ]]; then
		rm -f /var/log/nvidia-oc.log
		echo2 "> Loading ${GREEN}NVIDIA${NOCOLOR} drivers, $GPU_COUNT_NVIDIA GPU"
		modprobe nvidia_drm modeset=1
	fi
	pgrep --full nvidia-persistenced > /dev/null || nvidia-persistenced --persistence-mode

	if [[ $GPU_COUNT_AMD -gt 0 ]]; then
		rm -f /var/log/amd-oc.log

		echo2 "> Loading ${RED}AMD${NOCOLOR} drivers, $GPU_COUNT_AMD GPU"
		modprobe amdgpu

		echo2 "`amd-save-pp_tables`"

		# Moved here from gpu-detect
		amdmeminfo -q -s -n > $AMDMEMINFO_FILE 2>&1
		[[ -f $AMDMEMINFO_FILE ]] && amdmeminfo=`cat $AMDMEMINFO_FILE`
		# amdmeminfo can fail from the first time and skip some cards, let's rerun it
		if [[ `echo "$amdmeminfo" | wc -l` != $GPU_COUNT_AMD ]]; then
			sleep 0.1
			amdmeminfo -q -s -n > $AMDMEMINFO_FILE 2>&1
		fi
	fi
	#sleep 1
fi


# blacklist audio modules if present
mods=`lsmod | grep -oP "\K^snd[^\s]*"`
if [[ ! -z "$mods" ]]; then
	echo -e "\n#sound modules" >> /etc/modprobe.d/blacklist-hive.conf
	for mod in $mods; do
		echo "blacklist $mod" >> /etc/modprobe.d/blacklist-hive.conf
	done
	update-initgrub > /dev/null
fi


wd start

# allow to run Nvidia tools
rm /run/hive/NV_OFF > /dev/null 2>&1

gpu-detect listjson > $GPU_DETECT_JSON


### Loading continues ##################################################################

#commented, no one will see it
### tail syslog ############################################################################
#TAILPID=`ps aux | grep "tail -f /var/log/syslog" | grep -v grep | awk '{print $2}'`
#[ "0$TAILPID" != "0" ] && kill -9 $TAILPID
#tail -f /var/log/syslog > /dev/tty1 &

#motd


#Run watchdog pinger ASAP. Will detect device.
echo2 "> Detecting watchdogs"
echo2 "`/hive/opt/watchdoginua/watchdoginua.sh`"
echo2 "`/hive/opt/opendev/watchdog-opendev.sh`"
echo2 "`/hive/opt/esonics/watchdog-esonics.sh`"
echo2 "`/hive/opt/qinheng/hl340.sh`"
echo2 "`/hive/opt/srrv2/srrv2.sh`"
echo2 "`/hive/opt/octofan/watchdog-octofan.sh`"


echo2 "> Applying crontab"
crontab /hive/etc/crontab.root


echo2 "> Saying hello to server"
hello boot verbose nocolor
[[ -f $RIG_CONF ]] && source $RIG_CONF


# Setup locale maybe on the very first run
#[[ ! -z "$SYSTEM_LANG" ]] &&
#	locale-setup "$SYSTEM_LANG" &&
#	export LC_ALL="$SYSTEM_LANG"

# cache host only if network is online to reduce boot time. it will be run by cron anyway
if networkctl list | grep -q routable; then
	echo2 "> Caching host resolve"
	cache-hive-ip nocolor
fi

echo2 "> Starting agent screen"
agent-screen start


#starting average hashrate calculating service
[[ $SEND_AVG_KHS -eq 1 ]] && avg_khs start


# always generate X server config
echo2 "> Creating X server config"
echo2 "`xorg-conf`"


# auto enable X server for Nvidia gpu
[[ -z $X_DISABLED && $GPU_COUNT_NVIDIA -gt 0 ]] && X_DISABLED=0

if [[ $X_DISABLED == 0 && $MAINTENANCE != 2 ]]; then
	echo2 "> Starting X Server"

	# don't know why by this fixes amdgpu 17.40 bug
	# xf86OpenConsole: Switching VT failed
	# maybe time needed to allocate VTs...
	sleep 2

	if ! hivex start >/dev/null; then
		echo2 "\n${RED}It seems X server failed to run.\nThis can happen with some GPUs and buggy drivers.${NOCOLOR}\n"
		sleep 3
	fi
fi


# Sync CUDA RTL symlinks
[[ $GPU_COUNT_NVIDIA -gt 0 ]] && nvidia-driver-update --cuda


#echo2 "> Starting octofan"
$OCTOFAN


# Apply OC before miner start
if [[ $MAINTENANCE != 2 ]]; then
	if [[ $GPU_COUNT_NVIDIA -gt 0 ]]; then
		echo2 "> Applying Nvidia OC"
		nvidia-oc | sed 's/\x1b\[[0-9;]*m//g' # remove colors from syslog
	fi
	if [[ $GPU_COUNT_AMD -gt 0 ]]; then
		echo2 "> Applying AMD OC"
		amd-oc | sed 's/\x1b\[[0-9;]*m//g' # remove colors from syslog
	fi
	if [[ $GPU_COUNT_INTEL -gt 0 ]]; then
		echo2 "> Applying INTEL OC"
		intel-oc | sed 's/\x1b\[[0-9;]*m//g' # remove colors from syslog
	fi
	tweakers
fi


if [[ $MAINTENANCE == 1 || $MAINTENANCE == 2 ]]; then
	echo2 "> Maintenance mode. Miner and software watchdog are disabled"
else
	if [[ $MINER_DELAY -gt 0 ]]; then
		echo2 "Waiting $MINER_DELAY seconds before start miner"
		sleep $MINER_DELAY
	fi

	#check the unfinished Benchmark, and continue if found
	if [[ $bench == 1 ]]; then
		echo2 "> Unfinished benchmark found. Continue Benchmark"
		benchmark start
	else
		echo2 "> Starting miner"
		miner start
	fi
fi


[[ $MAINTENANCE != 2 ]] &&
	echo2 "> Starting autofan" &&
	autofan start


# AMD k10temp module
if [[ "$(< /proc/cpuinfo)" =~ AuthenticAMD ]]; then
	/hive/opt/k10temp/install.sh quiet | sed 's/\x1b\[[0-9;]*m//g' # remove colors from syslog
	modprobe k10temp
fi

echo2 "> System start complete"

# start console
systemctl restart hive-console

exit 0
