#!/usr/bin/env bash

SWITCH_OUTPUT_TO_MONITOR=1

set -o pipefail

#echo "Creating Xorg config"

source /hive/etc/gpu.ids

# disable glamregl extension as it often crashes X server
[[ -f /usr/lib/xorg/modules/libglamoregl.so ]] &&
	mv -f /usr/lib/xorg/modules/libglamoregl.so /usr/lib/xorg/modules/libglamoregl.so.disabled
[[ -f /opt/amdgpu/lib/xorg/modules/libglamoregl.so ]] &&
	mv -f /opt/amdgpu/lib/xorg/modules/libglamoregl.so /opt/amdgpu/lib/xorg/modules/libglamoregl.so.disabled


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

#amd_first=`gpu-detect AMD_FIRST`
#amd_busids=(`jq -c '[ . | to_entries[] | select(.value.brand == "amd") | .value.busid ] | .[]' <<< "$gpu_detect_json" 2>/dev/null`)
#nvidia_busids=(`jq -c '[ . | to_entries[] | select(.value.brand == "nvidia") | .value.busid ] | .[]' <<< "$gpu_detect_json" 2>/dev/null`)


convert_busid() {
	local busid=($1)
	local busid_arr=(${busid[0]//[!0-9a-fA-F]/ })
	echo "$((16#${busid_arr[0]})):$((16#${busid_arr[1]})):$((16#${busid_arr[2]}))"
}


gpu_detect="`lspci | grep -E "$GPU_DETECT_STRING"`"

amd_primary=`echo "$gpu_detect" | head -n 1 | grep "AMD" | grep -vE "$GPU_AMD_INTERNAL" | wc -l`
readarray -t amd_busids < <(echo "$gpu_detect" | grep "AMD" | grep -vE "$GPU_AMD_INTERNAL" | cut -d" " -f1)
#echo "AMD - ${amd_busids[@]}"

nvidia_primary=`echo "$gpu_detect" | head -n 1 | grep "NVIDIA" | grep -vE "$GPU_NVIDIA_INTERNAL" |  wc -l`
readarray -t nvidia_busids < <(echo "$gpu_detect" | grep "NVIDIA" | grep -vE "$GPU_NVIDIA_INTERNAL" | cut -d" " -f1)
#echo "NV - ${nvidia_busids[@]}"

internal=`echo "$gpu_detect" | head -n 1 | grep -vE "NVIDIA|AMD"`
#internal="`echo "$gpu_detect" | head -n 1 | grep -v "NVIDIA"`"
#[[ "$internal" =~ "AMD" && ! "$internal" =~ ($GPU_AMD_INTERNAL) ]] && internal=
#echo "INTERNAL - $internal"


devidx=0
screens_section=
conf=
connected=


# detect connected monitors
devices=(`grep "^connected" /sys/class/drm/*/status 2>/dev/null`)
if [[ ${#devices[@]} -gt 0 ]]; then
	monitors=()
	echo "Detecting connected monitors:"
	for device in "${devices[@]}"; do
		echo -n "  $device"
		dev_path="${device%%-*}/device/uevent"
		busid=
		[[ -f $dev_path ]] && busid=`grep -oP "PCI_SLOT_NAME=\K.*" $dev_path 2>/dev/null` && monitors+=(${busid/0000:})
		[[ ! -z $busid ]] && echo " - GPU $busid" || echo " - unable to get busid for GPU"
	done
fi
if [[ ! -z ${monitors[0]} ]]; then
	connected=${monitors[0]}
	if [[ "$internal" =~ $connected ]]; then
		gpu="internal"
	elif [[ "${amd_busids[@]}" =~ $connected ]]; then
		gpu="AMD"
	elif [[ "${nvidia_busids[@]}" =~ $connected ]]; then
		gpu="NVIDIA"
	else
		gpu="Unknown"
	fi
#	if [[ $SWITCH_OUTPUT_TO_MONITOR == 1 ]]; then
#		echo "Using $gpu GPU ${monitors[0]} as the primary one"
#	else
#		echo "Using default primary GPU"
#	fi
else
	SWITCH_OUTPUT_TO_MONITOR=0
fi


# add internal GPU only if it is primary or has connected monitor
if [[ ! -z $internal && ( $SWITCH_OUTPUT_TO_MONITOR != 1 || "$internal" =~ $connected ) ]]; then
	busid=`echo "$internal" | awk '{print $1}'`
	busid_dec=$(convert_busid $busid)

	internal_driver="vesa" # default
	[[ $internal =~ "Intel" ]] && internal_driver="intel" # 00:02.0 VGA compatible controller: Intel Corporation HD Graphics 610
	[[ $internal =~ "VMware" ]] && internal_driver="vmware" # 00:02.0 VGA compatible controller: VMware SVGA II Adapter
	[[ $internal =~ "Device 1234:1111" ]] && internal_driver="vesa"
	[[ $internal =~ "QXL" ]] && internal_driver="vga" #internal_driver="modesetting", with modesetting driver - OC will not work
	[[ $internal =~ "AMD" ]] && internal_driver="amdgpu"
	[[ $internal =~ "ASPEED" ]] && internal_driver="fbdev"

	if [[ ! -z $connected && "$internal" =~ $connected ]]; then
		echo "Adding internal GPU $busid with \"$internal_driver\" driver, as the primary one"
		monitor=
	else
		echo "Adding internal GPU $busid with \"$internal_driver\" driver, it is the primary one"
		monitor="Monitor        \"Monitor0\""
	fi

	conf+="
# --- Internal GPU -------------------------------------------------------------
Section \"Device\"
	Identifier     \"Device$devidx\"
	Driver         \"$internal_driver\"
	BusID          \"PCI:$busid_dec\"
EndSection

Section \"Screen\"
	Identifier     \"Screen$devidx\"
	Device         \"Device$devidx\"
	$monitor
EndSection
"
	screens_section+=$'\t'"Screen $devidx \"Screen$devidx\" 0 0"$'\n'
	((devidx++))
elif [[ ! -z $internal ]]; then
	echo "Detected internal GPU, skipping"
fi


# add AMD GPU only if it is primary or has connected monitor
if [[ ( $amd_primary -gt 0 && $SWITCH_OUTPUT_TO_MONITOR != 1 ) || ( $SWITCH_OUTPUT_TO_MONITOR == 1 && "${amd_busids[@]}" =~ $connected ) ]]; then

	# first add with connected monitor if needed
	if [[ $SWITCH_OUTPUT_TO_MONITOR == 1 && "${amd_busids[@]}" =~ $connected ]]; then
		echo "Adding ${#amd_busids[@]} AMD GPU, $connected as the primary one"
		busid=$connected
		busid_dec=$(convert_busid $busid)
		conf+="
# --- $busid -------------------------------------------------------------------
Section \"Device\"
	Identifier     \"Device$devidx\"
	Driver         \"amdgpu\"
	BusID          \"PCI:$busid_dec\"
EndSection

Section \"Screen\"
	Identifier     \"Screen$devidx\"
	Device         \"Device$devidx\"
EndSection
"
		screens_section+=$'\t'"Screen $devidx \"Screen$devidx\" 0 0"$'\n'
		((devidx++))
	else
		echo "Adding ${#amd_busids[@]} AMD GPU, first is the primary one"
	fi

	for busid in "${amd_busids[@]}"; do
		# skip already added
		[[ $SWITCH_OUTPUT_TO_MONITOR == 1 && $busid == $connected ]] && continue

		busid_dec=$(convert_busid $busid)
		conf+="
# --- $busid -------------------------------------------------------------------
Section \"Device\"
	Identifier     \"Device$devidx\"
	Driver         \"amdgpu\"
	BusID          \"PCI:$busid_dec\"
EndSection

Section \"Screen\"
	Identifier     \"Screen$devidx\"
	Device         \"Device$devidx\"
EndSection
"
		screens_section+=$'\t'"Screen $devidx \"Screen$devidx\" 0 0"$'\n'
		((devidx++))
	done

elif [[ ${#amd_busids[@]} -gt 0 ]]; then
	echo "Detected ${#amd_busids[@]} AMD GPU, skipping"
fi


# add Nvidia GPU in any case
if [[ ${#nvidia_busids[@]} -gt 0 ]]; then
	#monitors=(`nvidia-smi --query-gpu=gpu_bus_id,display_mode --format=csv,noheader 2>/dev/null | grep "Enabled" | cut -d, -f1`)

	skip=0

	if [[ $devidx -eq 0 && $SWITCH_OUTPUT_TO_MONITOR == 1 && "${nvidia_busids[@]}" =~ $connected ]]; then
		echo "Adding ${#nvidia_busids[@]} NVIDIA GPU, $connected as the primary one"
		skip=1
	elif [[ $devidx -eq 0 ]]; then
		echo "Adding ${#nvidia_busids[@]} NVIDIA GPU, first is the primary one"
	else
		echo "Adding ${#nvidia_busids[@]} NVIDIA GPU"
	fi

	for busid in "${nvidia_busids[@]}"; do
		disableDisplayDevice="Option         \"UseDisplayDevice\" \"none\""
		emulated_monitor_string="Option         \"ConnectedMonitor\" \"DFP-0\""$'\n'$'\t'"Option         \"CustomEDID\" \"DFP-0:/hive/etc/edid.bin\""

		# do not disable primary and connected outputs
		[[ $devidx -eq 0 && $SWITCH_OUTPUT_TO_MONITOR != 1 ]] && disableDisplayDevice=""
		[[ $busid == $connected ]] &&  emulated_monitor_string="" && disableDisplayDevice=""
		# set output to connected monitor
		if [[ $busid == $connected && $skip -eq 1 ]]; then
			skip=0
			screens_section+=$'\t'"Screen 0 \"Screen$devidx\" 0 0"$'\n'
		else
			screens_section+=$'\t'"Screen $(( devidx + skip )) \"Screen$devidx\" 0 0"$'\n'
		fi

		busid_dec=$(convert_busid $busid)
		conf+="
# --- $busid -------------------------------------------------------------------
Section \"Device\"
	Identifier     \"Device$devidx\"
	Driver         \"nvidia\"
	Option         \"Coolbits\" \"31\"
	Option         \"Interactive\" \"Off\"
	BusID          \"PCI:$busid_dec\"
	$emulated_monitor_string
EndSection

Section \"Screen\"
	Identifier     \"Screen$devidx\"
	Device         \"Device$devidx\"
	Option         \"Coolbits\" \"31\"
	$disableDisplayDevice
EndSection
"
		((devidx++))
	done
fi


# write config
echo "
#### AUTOGENERATED BY H. ####################################################################

Section \"ServerFlags\"
	Option \"BlankTime\" \"0\"
	Option \"StandbyTime\" \"0\"
	Option \"SuspendTime\" \"0\"
	Option \"OffTime\" \"0\"
EndSection

Section \"ServerLayout\"
	Identifier     \"Layout0\"

$screens_section
	InputDevice    \"Mouse0\" \"CorePointer\"
EndSection

Section \"Module\"
	Disable \"glx\"
EndSection

###############################################################################################

Section \"InputDevice\"
	Identifier     \"Mouse0\"
	Driver         \"mouse\"
	Option         \"Protocol\" \"auto\"
	Option         \"Device\" \"/dev/psaux\"
	Option         \"Emulate3Buttons\" \"no\"
	Option         \"ZAxisMapping\" \"4 5\"
EndSection

Section \"InputDevice\"
	Identifier     \"Keyboard0\"
	Driver         \"kbd\"
EndSection

###############################################################################################

Section \"Monitor\"
	Identifier     \"Monitor0\"
#	VendorName     \"Unknown\"
#	ModelName      \"Unknown\"
#	HorizSync       28.0 - 33.0
#	VertRefresh     43.0 - 72.0
	Option         \"DPMS\" \"0\"
EndSection

$conf
" > /etc/X11/xorg.conf

exit 0

#--use-display-device="DFP-0"
#--allow-empty-initial-configuration \ #Allow the X server to start even if no connected display devices could be detected.
#--preserve-driver-name #By default nvidia-xconfig changes the  display  driver  to "nvidia" for all configured X screens; this option preserves the existing driver name of each X screen.
#nvidia-xconfig \
#	--enable-all-gpus \
#	--cool-bits=31 \
#	--connected-monitor="DFP-0" \
#	--custom-edid="DFP-0:/hive/etc/edid.bin" \
#	--preserve-driver-name
