#!/usr/bin/env bash


export PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/sbin:/usr/local/bin:$PATH"

# prevent running from pipe
if [ $0 = "sh" ] || [ $0 = "bash" ]; then
	sleep 1
	echo "hive-replace does not work from pipe!"
	exit 1
fi

DIR=`pwd`
SCRIPT_PATH=$( cd $(dirname ${BASH_SOURCE[0]}) && pwd )
SCRIPT_NAME=`basename "$0"`

# repo list
REPO_LIST=/etc/apt/sources.list.d/hiverepo.list

[[ -e /etc/brand.conf ]] && source /etc/brand.conf
if [[ -z $DOWNLOAD_URL ]]; then
	# main url to images repo
	DOWNLOAD_URL=https://download.hiveos.farm
	# direct urls to images
	STABLE_URL=$DOWNLOAD_URL/latest/
	BETA_URL=$DOWNLOAD_URL/beta/
	#VEGA_URL=$DOWNLOAD_URL/vega/
	# images archive
	IMAGES_URL=$DOWNLOAD_URL/history/
else
	IMAGES_URL=$DOWNLOAD_URL
fi

[[ -z $OS_BRAND ]] && OS_BRAND="hiveos"
[[ -z $BRAND ]] && BRAND="Hive"
[[ -z $HIVE_HOST_URL ]] && HIVE_HOST_URL="https://api.hiveos.farm"

# image file mask
OS_REGEX="$OS_BRAND-[^\"]+\.(zip|xz)"
URL_MASK="^(http|ftp|https)://.*/${OS_REGEX}$"
ARCHIVE_REGEX="(\"|^)\K${OS_REGEX}(?=(\"|$))"

# download timeout
TIMEOUT=20

TMPDIR="/tmp/tmphive"
md5_url=
url=
root_dev=""
farm_hash=""
farm=""
force=0
no_confirm=0
smb=0
smbuser=
smbpasswd=
nfs=0
thishive=0
checked=0
download_path=


NOCOLOR=$'\033[0m'
BLACK=$'\033[0;30m'
DGRAY=$'\033[1;30m'
RED=$'\033[0;31m'
BRED=$'\033[1;31m'
GREEN=$'\033[0;32m'
BGREEN=$'\033[1;32m'
YELLOW=$'\033[0;33m'
BYELLOW=$'\033[1;33m'
BLUE=$'\033[0;34m'
BBLUE=$'\033[1;34m'
PURPLE=$'\033[0;35m'
BPURPLE=$'\033[1;35m'
CYAN=$'\033[0;36m'
BCYAN=$'\033[1;36m'
LGRAY=$'\033[0;37m'
WHITE=$'\033[1;37m'
GRAY=$'\033[2;37m'

[[ $(uname -sr) == *$OS_BRAND* || -d /hive-config ]] && thishive=1



function exit_handler {
	echo -e "\npress any key to close session"
	if [[ -t 0 ]]; then
		read -n 1
	else
		read -n 1 -t 600
	fi
}


function url_decode() {
	echo -e "${1//%/\\x}"
}


function get_image_from_url { # return $url
	local from_url=$( url_decode "$1" )
	local name=$2
	set -o pipefail
	url=`curl --connect-timeout $TIMEOUT --retry 2 -fskL --head -w '%{url_effective}' "$from_url" 2>/dev/null | tail -n 1`
	if [[ $? -eq 0 ]]; then
		[[ "$url" =~ $URL_MASK ]] && return 0
		echo -e "$RED> Got bad url for $name image - $url${NOCOLOR}"
		return 1
	fi
	echo -e "$RED> Unable to get url for $name image${NOCOLOR}"
	return 2
}


function get_image_from_list {
	local select="$1"
	local repo="$2"

	[[ -z "$repo" ]] && URL=$IMAGES_URL || URL="$repo"
	# trailing slash needed
	[[ ! "$URL" =~ /$ ]] && URL+="/"

	echo -e "${CYAN}> Loading $BRAND OS images list from ${BCYAN}${URL}${NOCOLOR}"

	local urls=()
	local arr=()
	declare -A IMAGE=()

	# skip for custom repo
	if [[ -z "$repo" ]]; then
		[[ ! -z $STABLE_URL ]] && get_image_from_url $STABLE_URL "Stable" && urls+=("$url") && IMAGE["$url"]="Latest Stable"
		[[ ! -z $BETA_URL ]] && get_image_from_url $BETA_URL "Beta" && urls+=("$url") && IMAGE["$url"]="Latest Beta"
		[[ ! -z $VEGA_URL ]] && get_image_from_url $VEGA_URL "Vega" && urls+=("$url") && IMAGE["$url"]="Latest Vega"
		url=
	fi

	local list
	if [[ -e "$URL" ]]; then
		# local path
		list=`ls -l "$URL" 2>/dev/null` &&
			readarray -t arr < <( echo "$list" | grep -oP "$OS_REGEX" | sort -n -t "@" -k1 )
	else
		# works for ftp also
		list=`curl -fskL --list --connect-timeout $TIMEOUT --retry 2 "$URL" 2>/dev/null` &&
			readarray -t arr < <( echo "$list" | grep -oP "$ARCHIVE_REGEX" | sed 's/%40/@/g' | sort -r -n -t "@" -k 2 ) ||
				echo -e "${RED}> Unable to load images list from repository${NOCOLOR}"
	fi

	local img
	for img in "${arr[@]}"; do
		[[ ! -z "${IMAGE["${URL}${img}"]}" ]] && continue # "
		urls+=("${URL}${img}")
		if [[ -f "${URL}${img}" ]]; then
			IMAGE["${URL}${img}"]="$(stat -c %s ${URL}${img} 2>/dev/null | awk '{printf "%d", $1/1e6}') MB"
		else
			IMAGE["${URL}${img}"]=""
		fi
	done

	[[ ${#urls[@]} -eq 0 ]] && echo -e "${RED}> List is empty${NOCOLOR}" && return 1

	# get images description
	local versions=
	# try to get from repo URL if specified
	[[ ! -z "$repo" ]] && versions=`curl -fsLk --connect-timeout $TIMEOUT --retry 2 "${URL}VERSIONS.txt" 2>/dev/null`
	# try to get from Hive server
	[[ -z $versions ]] && versions=`curl -fsLk --connect-timeout $TIMEOUT --retry 2 "${DOWNLOAD_URL}/VERSIONS.txt" 2>/dev/null`
	[[ -z $versions ]] && echo -e "${RED}> Unable to load image descriptions${NOCOLOR}"
	local SEP=" · "
	local index=0

	if [[ -z "$download_path" ]]; then
		echo -e "${YELLOW}> Select version to install${NOCOLOR}"
		printf "%b%2s) %b\n" $WHITE $index "${NOCOLOR}Exit"
	elif [[ "$select" != -1 ]]; then
		echo -e "${YELLOW}> Select version for download to ${BYELLOW}${download_path}${NOCOLOR}"
		printf "%b%2s) %b\n" $WHITE $index "${NOCOLOR}Exit"
	fi

	for img in "${urls[@]}"
	do
		local ver=`basename "$img" 2>/dev/null`
		info=`echo "$versions" | tr '\n' '|' | sed 's/||/\n/g' | grep "$ver" | tr '|' '\n'`
		# try without extension
		if [[ -z "$info" ]]; then
			[[ "$ver" =~ ^(.*)(\.zip|\.img\.xz)$ ]] &&
				name="${BASH_REMATCH[1]}" &&
				info=`echo "$versions" | tr '\n' '|' | sed 's/||/\n/g' | grep "$name" | tr '|' '\n'`
		fi
		#echo "$info"
		[[ ! -z "${IMAGE["$img"]}" ]] && ver+="${SEP}${WHITE}${IMAGE["$img"]}${NOCOLOR}"
		if [[ ! -z "$info" ]]; then
			#[[ "$info" =~ (\ [0-9]+\.[0-9]+\.[0-9]+)- ]] && ver+="${SEP}${CYAN}K${NOCOLOR}${BASH_REMATCH[1]}"
			kernel=`echo "$info" | grep -m1 -ioP "Linux [^0-9]*\K[0-9]+\.[0-9]+\.[0-9]+"` && ver+="${SEP}${CYAN}K${NOCOLOR} $kernel"
			nvidia=`echo "$info" | grep -m1 -ioP "^nvidia[^\s]* \K.*"` && ver+="${SEP}${GREEN}N${NOCOLOR} $nvidia"
			amd=`echo "$info" | grep -m1 -ioP "^amd[^\s]* \K.*"` && ver+="${SEP}${RED}A${NOCOLOR} $amd"
			#boot=`echo "$info" | grep -m1 "^Dual"` && ver+="${SEP}$boot"
			# get last line for desc
			desc=`echo "$info" | tail -n 1 | grep -ivP "^(amd|nvidia|Linux|md5|$OS_BRAND)"` && ver+="${SEP}$desc"
		fi
		((index++))
		printf "%b%2s) %b\n" $WHITE $index "${NOCOLOR}$ver"
	done

	if [[ -z "$select" ]]; then
		# allow to select only in interactive shell
		[[ ! -t 0 ]] && echo -e "${RED}Run in interactive shell to select image or use ${WHITE}--list=${CYAN}N${NOCOLOR}" && return 1
	elif [[ "$select" == -1 ]]; then
		return 0
	else
		[[ ! "$select" =~ ^[0-9]+$ || $select -lt 1 || -z ${urls[$(( select - 1 ))]} ]] &&
			echo -e "${RED}Invalid selection, exiting${NOCOLOR}" &&
			return 1
		url=`url_decode "${urls[$(( $select - 1 ))]}"`
		echo "${GREEN}> $select${NOCOLOR}"
		return 0
	fi

	while true;
	do
		read -p "> " REPLY
		[[ "$REPLY" == "0" || "$REPLY" = "exit" || "$REPLY" = "q" ]] && return 1
		[[ $REPLY -gt 0 && $REPLY -le ${#urls[@]} ]] && break
		echo -e "${RED}Invalid selection${NOCOLOR}"
	done
	((REPLY--))
	url=$( url_decode "${urls[$REPLY]}" )
	return 0
}


function check_packages {
	[[ $checked -eq 1 ]] && return 0

	local need_install=(lsof curl wget unzip unzip gdisk xz-utils)
	[[ $smb -eq 1 ]] && need_install+=(smbclient)
	[[ $nfs -eq 1 ]] && need_install+=(nfs-common)

	for idx in "${!need_install[@]}"; do
		dpkg -s "${need_install[$idx]}" > /dev/null 2>&1 && unset 'need_install[idx]'
	done

	if [[ ! -z "${need_install[@]}" ]]; then
		echo -e "${CYAN}> Installing required packages: ${WHITE}${need_install[@]}${NOCOLOR}"
		apt update
		apt install -y "${need_install[@]}"
		[[ $? -ne 0 ]] && echo -e "${RED}Failed to install required packages${NOCOLOR}" && exit 1
		echo -e "${GREEN}> Installed required packages successfully${NOCOLOR}\n"
	fi
	checked=1
}


# Gets/downloads image
function get_image {
	cd $TMPDIR
	rm $TMPDIR/*$OS_BRAND* > /dev/null 2>&1

	archname=`basename "$url"`

	if [[ $nfs -eq 1 || $smb -eq 1 ]]; then
		[[ ! -d $TMPDIR/share ]] && mkdir $TMPDIR/share
		mnt_flag=1
		mnt_share=1
		cat /proc/mounts | grep $TMPDIR/share > /dev/null 2>&1
		mnt_share=$?
		[[ $mnt_share -eq 0 ]] && mnt_flag=0
		[[ $nfs -eq 1 && $mnt_share -ne 0 ]] && mount -t nfs $(dirname "$url") $TMPDIR/share > /dev/null 2>&1 && mnt_flag=$?
		if [[ $smb -eq 1 && $mnt_share -ne 0 ]]; then
			psw=
			[[ -z $smbuser ]] && smbuser="nobody"
			[[ ! -z $smbpasswd ]] && psw="password=$smbpasswd"
			mount -v -t cifs -o username=$smbuser,$psw,iocharset=utf8,vers=3.0 $(dirname "$url") $TMPDIR/share > /dev/null 2>&1
			mnt_flag=$?
		fi
		[[ $mnt_flag -ne 0 ]] && echo -e "${RED}Can't mount network shared resource.${NOCOLOR}" && return 1
		url="$TMPDIR/share/$archname"
	fi

	echo -e "\n${CYAN}> Getting image size${NOCOLOR}"
	if [[ $nfs -eq 1 || $smb -eq 1 || -e "$url" ]]; then
		archsize=`stat --format=%s "$url" | awk '{print int($1/1000000)}'`
	else
		archsize=`curl -s --head "$url" | grep -ioP "content-length:[^0-9]+\K[0-9]+" | awk '{print int($1/1000000)}'`
	fi

	if [[ $? -eq 0 && ! -z "$archsize" ]]; then
		echo -e "${GREEN}Image size: ${WHITE}$archsize MB${NOCOLOR}"
		reqmem=$(( `free -m | grep 'Mem' | awk '{print $7}'` - archsize - 150 ))
		if [[ $force -eq 1 && $reqmem -lt 0 ]]; then
			echo -e "${RED}Image is to big to fit in RAM ($reqmem MB), exiting${NOCOLOR}"
			[[ $thishive -eq 1 ]] && echo -e "${YELLOW}Try to boot in maintenance mode without loading drivers${NOCOLOR}"
			return 1
		fi
	else
		[[ $force -eq 1 ]] && echo -e "${RED}Unable to get image size, exiting${NOCOLOR}" && return 1
		echo -e "${RED}Unable to get image size${NOCOLOR}"
	fi

	# download VERSIONS.txt to get md5 later
	#if [[ $force -ne 1 ]]; then
	#	#default is "http://download.hiveos.farm/VERSIONS.txt"
	#	md5_url=$(dirname "$url")/VERSIONS.txt
	#	#curl -s $md5_url > $TMPDIR/VERSIONS.txt
	#	wget -q -O $TMPDIR/VERSIONS.txt $md5_url
	#	[[ $? -ne 0 ]] && echo -e "${RED}Can't get $md5_url to check MD5 checksum. Use -f to ignore this.${NOCOLOR}" && return 1
	#	mdsum=$(sed -n "/$archname/p" $TMPDIR/VERSIONS.txt | awk '{printf$2}')
	#	[[ -z $mdsum ]] && echo -e "${RED}Can't get md5sum from $md5_url to check MD5 checksum. Use -f to ignore this.${NOCOLOR}" && return 1
	#fi

	# stop miner here to free some memory and prevent rig from rebooting on errors
	#[[ $thishive -eq 1 ]] && miner stop 2>/dev/null

	# Copy|download hive image to tmpfs
	echo -e "\n${CYAN}> Downloading image file${NOCOLOR}"
	if [[ "$url" == http* ||  "$url" == ftp* ]]; then
		echo ""
		wget -t 0 -T $TIMEOUT --no-check-certificate "$url"
		[[ $? -ne 0 ]] && echo -e "${RED}Download $BRAND OS image failed. Check url${NOCOLOR}" && return 1
	else
		[[ ! -f $url ]] && echo -e "${RED}$BRAND OS image not found. Check path${NOCOLOR}" && return 1
		cp -v $url $TMPDIR
		[[ $? -ne 0 ]] && echo -e "${RED}Copy $BRAND OS image failed${NOCOLOR}" && return 1
	fi

	# check md5
	#if [[ $force -ne 1 ]]; then
	#	echo -e "\n${CYAN}> Checking MD5 of image file${NOCOLOR}"
	#	mdsum_hive=$(md5sum $TMPDIR/$archname | awk '{printf$1}')
	#	[[ $mdsum != $mdsum_hive ]] && echo -e "${RED}MD5 checksum of image file does not match${NOCOLOR}\nGot $mdsum_hive, expected $mdsum" && return 1
	#fi

	# check archive integrity
	echo -e "\n${CYAN}> Checking archive integrity${NOCOLOR}"
	if [[ $archname == *\.xz ]]; then
		xz -t --verbose $TMPDIR/$archname > /dev/null
	else #if [[ $archname == *\.zip ]]; then
		unzip -t $TMPDIR/$archname > /dev/null
	fi
	[[ $? -ne 0 ]] && echo -e "${RED}Archive is damaged${NOCOLOR}" && return 1

	echo -e "${GREEN}$BRAND OS image ready!${NOCOLOR}"
	return 0
}


# Starting actions
function prepare {
	#[[ $(tty) == *tty* ]] && echo "This script does not work in the local console, exiting" && return 1
	if pstree -As $$ | grep -q "xinit"; then
		if [[ $thishive -ne 1 ]]; then
			echo -e "${RED}Hive-replace does not work in X server console!${NOCOLOR}"
			echo -e "${YELLOW}Run it from text local or remote shell${NOCOLOR}"
			return 1
		fi
		echo -e "${YELLOW}Hive-replace does not work in X server console!${NOCOLOR}"
		echo -e "${YELLOW}X server will be stopped now and process will continue${NOCOLOR}"
		sleep 5
		# stop X and restart console to resume hive-replace from motd
		hivex stop
		systemctl restart hive-console
	fi
	#pstree -As $$ | grep -q -P "(ssh|shellinabox|hive-console|screen)" || (echo -e "${YELLOW}Hive-replace does not work in X server console! Make sure it is not running from it${NOCOLOR}"; sleep 5)

	mem=$(free -m | awk 'NR == 2{print$2}')
	#clear
	echo -e "\n"
	echo -e "${CYAN}***********************************${NOCOLOR}"
	echo -e "${YELLOW}    $BRAND OS Image Installation${NOCOLOR}"
	echo -e "${CYAN}***********************************${NOCOLOR}"
	echo
	echo -e "$WHITE$url${NOCOLOR}"
	echo
	echo "Total RAM=$mem Mb"
	echo
	[[ $mem -lt 2900 && $force -ne 1 ]] && echo -e "${RED}At least 3 GB RAM is required, exiting${NOCOLOR}" && return 1

	#PART_UUID=`cat /proc/cmdline | tr " " "\n" | grep "UUID" | sed 's/\(^root=UUID=\)//'`
	PART_UUID=`grep -oP "root=UUID=\K[^\s]+" /proc/cmdline` &&
		DISK_PART=`blkid -U "${PART_UUID}" | sed 's/\(^\/dev\/\)//'` ||
		DISK_PART=`grep -oP "root=/dev/\K[^\s]+" /proc/cmdline`

	[[ -z $DISK_PART ]] && echo -e "${RED}Unable to determine root disk${NOCOLOR}" && return 1

	if [[ "$(echo $DISK_PART | grep -c nvme)" -gt 0 ]]; then
		DISK_NAME=${DISK_PART::-2} #cutoff partnumber pN
	else
		DISK_NAME=${DISK_PART::-1} #cutoff partnumber N
	fi
	DISK_SIZE=`cat /proc/partitions | grep -w "${DISK_NAME}" | awk '{ printf("%.f",$3/1024)}'`
	PART_SIZE=`cat /proc/partitions | grep -w "${DISK_PART}" | awk '{ printf("%.f",$3/1024)}'`

	echo -e "Current OS booted from ${BPURPLE}$DISK_NAME${NOCOLOR} and whole drive size is ${WHITE}$DISK_SIZE${NOCOLOR} Mb"
	[[ $DISK_SIZE -lt 7300 ]] && echo -e "\n${YELLOW}The minimum disk size for $BRAND OS is 8 Gb${NOCOLOR}" && exit

	if [[ $no_confirm -ne 1 ]]; then
		echo -e "${RED}Warning: After $BRAND OS installation, all your data on ${BPURPLE}$DISK_NAME${NOCOLOR} ${RED}will be lost!${NOCOLOR}"
		echo -en "\nType ${GREEN}\"yes\"${NOCOLOR} if you want to install $BRAND OS on ${BPURPLE}$DISK_NAME${NOCOLOR}: "
		read -t 90 answer
		[[ $answer != "yes" ]] && echo -e "${YELLOW}\nBye, bye!${NOCOLOR}" && exit 0
	fi

	# check programs
	check_packages

	# create tmpfs
	cat /proc/mounts | grep $TMPDIR > /dev/null 2>&1
	if [[ $? -ne 0 ]]; then
		mkdir $TMPDIR > /dev/null 2>&1
		mount none $TMPDIR -t tmpfs -o size=3000m
	fi

	# get farm_hash or old config
	mkdir -p $TMPDIR/old-config
	if [[ ! -z $farm ]]; then
		echo -e "HIVE_HOST_URL=\"$HIVE_HOST_URL\"" > ${TMPDIR}/old-config/rig.conf
		echo -e "FARM_HASH=$farm\n" >> ${TMPDIR}/old-config/rig.conf
	elif [[ -f /hive-config/rig.conf ]]; then
		cp /hive-config/rig.conf ${TMPDIR}/old-config/
	fi
	[[ -d /hive-config/network ]] && cp -R /hive-config/network $TMPDIR/old-config/
	[[ -d /hive-config/openvpn ]] && cp -R /hive-config/openvpn $TMPDIR/old-config/
	[[ -d /hive-config/watchdog ]] && cp -R /hive-config/watchdog $TMPDIR/old-config/

	# stop miner and some services to reduce RAM usage and prevent reboot

	if [[ $thishive -eq 1 ]]; then
		echo -e "\n${CYAN}> Stopping $BRAND OS services${NOCOLOR}"
		autoswitch stop > /dev/null 2>&1
		miner stop > /dev/null 2>&1
		autofan stop > /dev/null 2>&1
		systemctl stop hivex >/dev/null 2>&1
		sleep 1
		killall xinit > /dev/null 2>&1
		systemctl stop hive-watchdog
		#agent-screen stop
	fi

	# turn off swap here
	swapoff -a

	# get hive zip
	get_image || return

	# Disable kernel message to tty
	echo 0 > /proc/sys/kernel/printk
	echo 1 > /proc/sys/kernel/sysrq
	echo 0 > /proc/sysrq-trigger

	# stop services and remount RO
	echo -e "\n${CYAN}> Stopping services${NOCOLOR}"

	term=`tty | grep -oP "\Ktty[0-9]+"`
	[[ ! -z $term ]] && term="|$term"

	for service in `initctl list 2>/dev/null | grep "/running" | grep -v -P "network|ssh|shellinabox|openvpn$term" | awk '{print $1}'`; do
		initctl stop $service > /dev/null 2>&1 && echo "> stop $service";
		sleep 0.1
	done

	for service in `systemctl list-units 2>/dev/null | grep -oP "\K[^\s]+\.(service|socket)" | grep -v -P "ssh|openvpn|shellinabox|network|ifup|user|hive$term"`; do
		systemctl stop $service > /dev/null 2>&1 && echo "> stop $service";
		sleep 0.1
	done

	for i in {1..3}; do
		for pid in `lsof / | grep -v -P "^COMMAND|$SCRIPT_NAME| (mem|txt|rtd|cwd) |network|telec|hssh|watchdog|hl340|srrv2|hive-console|watchdog-octofan" | awk '{print $2}'`; do
			cmd=`ps -p $pid -o args | tail -n 1`
			kill -9 $pid 2>/dev/null && echo -e "> kill $pid: $cmd" && sleep 0.1
		done
		sleep 1
	done

	# Readonly remount
	for MOUNT in `cat /proc/mounts | grep $DISK_NAME | awk '{print $2}'`; do
		if [[ "$MOUNT" == "/hive-config" ]]; then
			umount -f $MOUNT > /dev/null 2>&1 && mount -n -o ro $MOUNT > /dev/null 2>&1
		else
			mount -n -o remount,ro $MOUNT > /dev/null 2>&1
		fi
		exitcode=$?
		[[ $exitcode -eq 0 ]] &&
			echo "> mount read-only: $MOUNT" ||
			echo "> mount read-only failed ($exitcode): $MOUNT"
	done


	# create temp root
	echo -e "\n${CYAN}> Creating temporary root filesystem${NOCOLOR}"
	mkdir -p $TMPDIR/{proc,sys,run,dev,usr,var,oldroot,bin,sbin,lib,tmp,usr/lib,usr/share,usr/lib/x86_64-linux-gnu,lib/lsb}
	cp -aR /{bin,sbin,etc} $TMPDIR > /dev/null 2>&1
	cp -aR /usr/{bin,sbin} $TMPDIR/usr > /dev/null 2>&1
	cp -aR /lib/x86_64-linux-gnu $TMPDIR/lib > /dev/null 2>&1
	cp -aR /lib64 $TMPDIR > /dev/null 2>&1
	cp -aR /usr/lib/sudo $TMPDIR/usr/lib > /dev/null 2>&1
	cp -a /usr/lib/x86_64-linux-gnu/libmpfr* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1
	cp -a /usr/lib/x86_64-linux-gnu/libsigsegv* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1
	cp -a /usr/lib/x86_64-linux-gnu/libgmp* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1
	cp -a /usr/lib/x86_64-linux-gnu/libstdc++* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1
	cp -a /usr/lib/x86_64-linux-gnu/libpopt.so* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1

	cp -a /usr/lib/x86_64-linux-gnu/libicu*.so* $TMPDIR/usr/lib/x86_64-linux-gnu > /dev/null 2>&1

	cp -aR /dev $TMPDIR > /dev/null 2>&1

	cp $SCRIPT_PATH/$SCRIPT_NAME $TMPDIR > /dev/null 2>&1
	chmod +x $TMPDIR/$SCRIPT_NAME > /dev/null 2>&1

	# create conf for second part
	echo "wr=1" > $TMPDIR/replace.conf
	echo "archname=$archname" >> $TMPDIR/replace.conf
	echo "root_dev=$DISK_NAME" >> $TMPDIR/replace.conf
	echo "conf_loop=$conf_loop" >> $TMPDIR/replace.conf
	echo "conf_part=${DISK_PART::-1}1" >> $TMPDIR/replace.conf

	# chroot to temp root
	mount --rbind /proc $TMPDIR/proc
	mount --rbind /sys $TMPDIR/sys
	mount --rbind /dev $TMPDIR/dev
	sync
	cd $TMPDIR
	exec chroot . /bin/bash /$SCRIPT_NAME
}


# Writing to disk
function write {
	cd /
	[[ -z $archname || ! -f $archname ]] && echo -e "${RED}> $BRAND OS image not found, exiting${NOCOLOR}" && return 1

	echo -e "\n${CYAN}> Writing $BRAND OS filesystem to ${BPURPLE}$root_dev${NOCOLOR}"
	echo -e "Please wait, this can take long"
	echo -e "To prevent damage to your disk device\ndo not turn off your computer until the end of the process.\n"

	if dd --help | grep -q "'progress'"; then
		if [[ $archname == *\.xz ]]; then
			xz -d -c $archname | dd of=/dev/$root_dev bs=1M status=progress
		else #if [[ $archname == *\.zip ]]; then
			unzip -p $archname | dd of=/dev/$root_dev bs=1M status=progress
		fi
		exitcode=$?
	else
		# show progress
		( sleep 2; while true; do sleep 1; pkill -USR1 -f "dd of=/dev/" || break; echo -en "\r$(tail -n 1 ./progress 2>/dev/null )      "; done) &
		if [[ $archname == *\.xz ]]; then
			xz -d -c $archname | dd of=/dev/$root_dev bs=1M 2>./progress
		else #if [[ $archname == *\.zip ]]; then
			unzip -p $archname | dd of=/dev/$root_dev bs=1M 2>./progress
		fi
		exitcode=$?
		[[ $exitcode -eq 0 ]] && echo -e "\r$(tail -n 1 ./progress 2>/dev/null)      "
	fi
	[[ $exitcode -ne 0 ]] && echo -e "${RED}Write image failed, exiting${NOCOLOR}" && return 2

	# Fix GPT table if needed
	sgdisk -e /dev/$root_dev > /dev/null 2>&1
	sgdisk -C /dev/$root_dev > /dev/null 2>&1
	partprobe /dev/$root_dev > /dev/null 2>&1

	# Rewrite config partition
	configured=0
	if [[ -f old-config/rig.conf ]]; then
	    # we do not need it any more
	    rm $archname > /dev/null 2>&1

		echo -e "\n${CYAN}> Writing $BRAND OS config to ${BPURPLE}$root_dev${NOCOLOR}"

		dd if=/dev/${conf_part} of=new_conf.img bs=1M

		LOOPDEV=$(losetup --find --show new_conf.img)
		partprobe ${LOOPDEV}

		mkdir hive-config
		mount ${LOOPDEV} hive-config
		if [[ $? -eq 0 ]]; then
			cp -R old-config/* hive-config
			sync
			dd if=/new_conf.img of=/dev/${conf_part} bs=1M
			configured=1
		else
			echo -e "${RED}Config was not written to ${BPURPLE}${conf_part}${NOCOLOR}"
		fi
	fi

	sync

	echo -e
	echo -e "${GREEN}Image writing to ${BPURPLE}$root_dev${GREEN} is successfull!${NOCOLOR}"
	echo -e
	echo -e "Your rig is configured and ready to work under $BRAND OS."

	if [[ $configured -eq 1 ]]; then
		[[ -f old-config/rig.conf ]] && source old-config/rig.conf
		[[ ! -z "$RIG_ID" && ! -z "$RIG_PASSWD" && ! -z "$HIVE_HOST_URL" ]] &&
			echo -e "RIG ID: $RIG_ID, API: $HIVE_HOST_URL"
	fi

	echo -e
	echo -e "${GREEN}Have a happy mining!${NOCOLOR}"

	return 0
}



function start {
	wr=0
	[[ -f "/replace.conf" ]] && source "/replace.conf"

	if [[ $wr -ne 1 ]]; then
		[[ -z "$url" ]] && echo -e "${YELLOW}Filesystem path or URL to $BRAND OS image is required.${NOCOLOR}\n" && usage
		prepare
	else
		write
		echo -e "${YELLOW}Rebooting in 20 seconds${NOCOLOR}"
		sleep 20
		# Reboot
		echo 1 > /proc/sys/kernel/sysrq
		echo b > /proc/sysrq-trigger
	fi
}


function usage {
	local code=$1
	echo -e "${CYAN}Usage: hive-replace [option] <Path or URL to ZIP/XZ file with $BRAND OS image>${NOCOLOR}"
	echo -e
	echo -e "Options:"
	echo -e "${GREEN}  -l|--list|--list=NUM    ${NOCOLOR}List images from $BRAND server and select for install (or download)"
	echo -e "${GREEN}  -s|--stable             ${NOCOLOR}Download and install latest ${BCYAN}Stable${NOCOLOR} image from $BRAND server"
	[[ ! -z $VEGA_URL ]] &&
		echo -e "${GREEN}  --vega                  ${NOCOLOR}Download and install latest ${CYAN}Vega${NOCOLOR} image from $BRAND server"
	[[ ! -z $BETA_URL ]] &&
		echo -e "${GREEN}  --beta                  ${NOCOLOR}Download and install latest ${CYAN}Beta${NOCOLOR} image from $BRAND server"
	echo -e "${GREEN}  --repo[=URL]            ${NOCOLOR}List images from custom repository (specified by URL) and select for install (HTTP(S)/FTP)"
	echo -e "${GREEN}  -y|--yes                ${NOCOLOR}Do not ask for confirmation, answer yes to all questions"
	echo -e "${GREEN}  --force                 ${NOCOLOR}Force replace if RAM is less than 3GB. Use on your own risk"
	echo -e "${GREEN}  --safe                  ${NOCOLOR}Run replace in safer way so running session can be resumed (run hive-replace or screen -r replace)"
	echo -e "${GREEN}  --download=PATH         ${NOCOLOR}Download image to PATH (without replace). Can be used with other options (--stable)"
	echo -e "${GREEN}  --hash=FARM_HASH        ${NOCOLOR}FARM_HASH from Web-interface. Optional for already configured rig"
	echo -e "${GREEN}  --nfs                   ${NOCOLOR}To use NFS Shared resource. e.g.: ${GREEN}IP_NFS_server:/shared_dir/image_file${NOCOLOR}"
	echo -e "${GREEN}  --smb                   ${NOCOLOR}To use Windows Shared resource. e.g.: ${GREEN}//IP_Windows_comp/shared_folder/image_file${NOCOLOR}"
	echo -e "${GREEN}  --smbuser=Windows user  ${NOCOLOR}UserName for Windows Shared resource. Do not set this option for guest/anonymous access"
	echo -e "${GREEN}  --smbpass=Windows pass  ${NOCOLOR}Password for Windows Shared resource. Do not set this option for guest/anonymous access"
	echo -e "${GREEN}  -h|--help               ${NOCOLOR}Show this message"
	[[ ! -z $code ]] && exit $code
	echo -e
	echo -e "Examples:"
	echo -e "${GREEN}  hive-replace -y --stable${NOCOLOR}"
	echo -e "${GREEN}  hive-replace -y --list${NOCOLOR}"
	echo -e "${GREEN}  hive-replace -y --list=3 --repo=http://mylocalserver/images/${NOCOLOR}"
	echo -e "${GREEN}  hive-replace -y --hash=46e9602837d0bda99f0 http://mylocalserver/$OS_BRAND-0.6.zip${NOCOLOR}"
	echo -e "${GREEN}  hive-replace -y --hash=46e9602837d0bda99f0 --nfs 192.168.10.100:/home/john/hive/$OS_BRAND-0.6.zip${NOCOLOR}"
	echo -e "${GREEN}  hive-replace -y --smb --smbuser=winuser --smbpass=secret //192.168.0.1/shared_folder/$OS_BRAND-0.6.xz${NOCOLOR}"
	exit 0
}


[[ $1 == "-h" || $1 == "--help" ]] && usage


# Get root
if [[ $(id -u) -ne 0 ]]; then
	echo "Root privileges required"
	sudo chmod +x $0
	exec sudo $0 "$@"
fi


# check for running session and restore to it
if [[ "`pstree -As $$`" != *-screen-* ]] && screen -ls replace 2>/dev/null | grep -q ".replace"; then
	echo -e "Hive-replace session is already running"
	if [[ -t 0 ]]; then
		echo -e "Resuming..."
		read -t 2 -n 1
		screen -x -S replace
	else
		echo -e "Use interactive shell to connect to it!"
	fi
	exit
fi


if [[ " $@ " =~ " --safe " || ($thishive -eq 1 && ! " $@ " =~ " --no-safe ") ]]; then
	if [[ "`pstree -As $$`" != *-screen-* ]]; then
		echo "Starting session"
		screen -mS replace $0 $@ && exit
		echo -e "${YELLOW}Session start failed. Running in common way...${NOCOLOR}"
	else
		# set exit handler to pause at the end
		trap exit_handler EXIT
	fi
fi


listparams=

for param in "$@"; do
	case "$param" in
		--safe|--no-safe)
			# ignore it here
		;;
		--force)
			force=1
		;;
		-y|--yes)
			no_confirm=1
		;;
		--nfs)
			nfs=1
		;;
		--smb)
			smb=1
		;;
		--smbuser=*)
			smbuser="${param#*=}"
		;;
		--smbpass=*)
			smbpasswd="${param#*=}"
		;;
		--hash=*)
			farm="${param#*=}"
		;;
		https://*$OS_BRAND*|http://*$OS_BRAND*|ftp://*$OS_BRAND*)
			check_packages
			get_image_from_url "$param" "this" || exit
		;;
		*$OS_BRAND*.xz|*$OS_BRAND*.zip)
			[[ -f "$DIR/$param" ]] && param="$DIR/$param"
			url=$( url_decode "$param" )
		;;
		-l|--list)
			listparams[2]=1
		;;
		-l=*|--list=*)
			[[ ! "${param#*=}" =~ ^[0-9]+$ ]] && echo -e "${RED}> Non-numeric value, exiting${NOCOLOR}" && exit 1
			listparams[0]="${param#*=}"
		;;
		--repo)
			[[ ! -f $REPO_LIST ]] && echo -e "${RED}> No default repository, exiting${NOCOLOR}" && exit 1
			repo=`grep -m1 -oP "deb\s*\K[^\s]+/repo/" $REPO_LIST`
			[[ -z "$repo" || "$repo" =~ "${DOWNLOAD_URL##*/}" ]] && echo -e "${RED}> No custom repository, exiting${NOCOLOR}" && exit 1
			listparams[1]="$repo"
		;;
		--repo=*)
			[[ -z ${param#*=} ]] && echo -e "${RED}> Repository URL is required, exiting${NOCOLOR}" && exit 1
			listparams[1]="${param#*=}"
		;;
		-s|--stable)
			if [[ -z $STABLE_URL ]]; then
				listparams[0]="1"
			else
				check_packages
				get_image_from_url $STABLE_URL "Stable" || exit
			fi
		;;
		--beta)
			[[ -z $BETA_URL ]] && exit
			check_packages
			get_image_from_url $BETA_URL "Beta" || exit
		;;
		--vega)
			[[ -z $VEGA_URL ]] && exit
			check_packages
			get_image_from_url $VEGA_URL "Vega" || exit
		;;
		--download=*)
			[[ -z ${param#*=} ]] && echo -e "${RED}> Download PATH is required, exiting${NOCOLOR}" && exit 1
			[[ ! -d ${param#*=} ]] && echo -e "${RED}> Provided PATH does not exist, exiting${NOCOLOR}" && exit 1
			download_path="${param#*=}"
		;;
		*)
			echo -e "${RED}Unknown param: ${WHITE}$param${RED}${NOCOLOR}\n" && usage 2
		;;
	esac
done


[[ $nfs -eq 1 && $smb -eq 1 ]] && echo -e "${YELLOW}Specify only one of the options: ${GREEN}--smb${NOCOLOR} or ${GREEN}--nfs${NOCOLOR}. Both are not allowed${NOCOLOR}\n" && usage 1
[[ ( $nfs -eq 1 || $smb -eq 1 ) && ( "$url" == *http* ||  "$url" == *ftp* ) ]] && echo -e "${YELLOW}--nfs or --smb and http or ftp - incompatible\n" && usage 1


# only download in specified path
if [[ ! -z "$download_path" ]]; then
	[[ ! "$download_path" =~ /$ ]] && download_path+=/
	check_packages
	get_image_from_list -1 "$download_path"
	echo
	# list images from default repo
	if [[ -z "$url" || ! -z "${listparams[@]}" ]]; then
		get_image_from_list "${listparams[0]}" "${listparams[1]}" || exit
	fi
	# download new
	TMPDIR="${download_path}tmp"
	mkdir -p $TMPDIR || exit 1
	get_image
	exitcode=$?
	if [[ $exitcode -eq 0 ]]; then
		mv -f $TMPDIR/*$OS_BRAND* $download_path
		#get_image_from_list -1 "$download_path"
	fi
	cd $DIR
	exit $exitcode
fi


if [[ ! -z "${listparams[@]}" ]]; then
	check_packages
	get_image_from_list "${listparams[0]}" "${listparams[1]}" || exit
fi


start
