#!/bin/bash

# require("device.db")

# in case there is no DEVICE_TABLE declared, we'll create a dummy table
# to prevent syntax errors
if ! declare -p DEVICE_TABLE 2>/dev/null | grep -q '^declare -[Aa]'; then
	unset DEVICE_TABLE
	declare -A DEVICE_TABLE
fi

# ref: http://wiki.osdev.org/PCI#Class_Codes

######## 01  : Mass Storage Controller

# 0200: Ethernet Controller
# 0280: Other Network Controller

# 0300: VGA-Compatible Controller
# 0302: 3D Controller (Not VGA-Compatible)
# 0380: Other Display Controller

FILTER_GPU_DEVICES='^03(00|02|80)'
FILTER_DGPU_DEVICES='^03(02|80)'
FILTER_IGPU_DEVICES='^0300'
FILTER_CORE_DEVICES='^(02(00|80)|03(00|02|80))'
FILTER_NET_DEVICES='^02(00|80)'

# [device] | filter_known_devices
filter_known_devices()
{
	while read device; do
		local pciid=$(device_get_pciid "$device")

		# TODO: no hard coding for table name
		if [ "${DEVICE_TABLE[$pciid]+isset}" ]; then
			echo "$device"
		fi
	done
}

# [device] | filter_unknown_devices
filter_unknown_devices()
{
	while read device; do
		local pciid=$(device_get_pciid "$device")

		# TODO: no hard coding for table name
		if ! [ "${DEVICE_TABLE[$pciid]+isset}" ]; then
			echo "$device"
		fi
	done
}

# [device] | filter_core_devices
filter_core_devices()
{
	egrep $FILTER_CORE_DEVICES
}

# [device] | filter_net_devices
filter_net_devices()
{
	egrep $FILTER_NET_DEVICES
}

# [device] | filter_igpu_devices
filter_igpu_devices()
{
	egrep $FILTER_IGPU_DEVICES
}

# [device] | filter_dgpu_devices
filter_dgpu_devices()
{
	egrep $FILTER_DGPU_DEVICES
}

# [device] | filter_gpu_devices
filter_gpu_devices()
{
	egrep $FILTER_GPU_DEVICES
}

# [pciid] | transform_pciid
transform_pciid()
{
	local ret=0
	while read pciid; do
		# TODO: no hard coding for table name
		if [ "${DEVICE_TABLE[$pciid]+isset}" ]; then
			echo "${DEVICE_TABLE[$pciid]}"
		else
			echo "unsupported device id: $pciid" >&2
			echo "$pciid"
			# unsupported device
			ret=1
		fi
	done

	return $ret
}

# [device] | transform_devices
transform_devices()
{
	local ret=0
	while read device; do
		local class=$(device_get_class "$device")
		local pciid=$(device_get_pciid "$device")

		# TODO: no hard coding for table name
		if [ "${DEVICE_TABLE[$pciid]+isset}" ]; then
			echo "${class}${DEVICE_TABLE[$pciid]}"
		else
			echo "unsupported device: $device" >&2
			echo "$device"
			# unsupported device
			ret=1
		fi
	done

	return $ret
}

# [pciid] | check_pciid
check_pciid()
{
	while read pciid; do
		# TODO: no hard coding for table name
		if ! [ "${DEVICE_TABLE[$pciid]+isset}" ]; then
			# unsupported device
			return 1
		fi
	done
}

# [device] | check_devices
check_devices()
{
	devices_get_pciid | check_pciid
}

# [device] | compose_config [arg...]
compose_config()
{
	if :; then
		paste -sd '-'

		for arg in "$@"; do
			echo "$arg"
		done
	fi | paste -sd ':'
}

# config_get_arg 'config' 'index'
# index count from 1
config_get_arg()
{
	local config="$1"
	local index="$(( $2 + 1 ))"

	if [ "$index" -gt 1 ]; then
		echo "$config" | cut -d':' -f "$index"
	else
		return 1
	fi
}

# config_get_args 'config'
config_get_args()
{
	local config="$1"
	echo "${config#*:}" | tr ':' '\n'
}

# config_get_devices 'config'
config_get_devices()
{
	local config="$1"
	echo "${config%%:*}" | tr '-' '\n'
}

# [device] | compose_cid [arg]
compose_cid()
{
	if :; then
		filter_gpu_devices \
			| devices_get_pciid \
			| transform_pciid \
			| sort \
			| paste -sd '-'

		for arg in "$@"; do
			echo "$arg"
		done
	fi | paste -sd ':'
}

# [device] | devices_get_class
devices_get_class()
{
	cut -b1-4
}

# [device] | devices_get_pciid
devices_get_pciid()
{
	cut -b5-12
}

# device_get_class 'device'
device_get_class()
{
	echo "$1" | devices_get_class
}

# device_get_pciid 'device'
device_get_pciid()
{
	echo "$1" | devices_get_pciid
}

# get_image_name
# output: sutton-base-trusty-amd64
get_image_name()
{
	[ -f /etc/buildstamp ] || return

	tail -n1 /etc/buildstamp \
		| grep -o '^[^-]\+-[^-]\+-[^-]\+-[^-]\+'
}

# get_image_index
# output: 20141209-0
get_image_index()
{
	[ -f /etc/buildstamp ] || return

	tail -n1 /etc/buildstamp \
		| grep -o '[^-]\+-[^-]\+$'
}

# get_image_stamp
# output: 09 Dec 2014 01:05:38 +0000
get_image_stamp()
{
	[ -f /etc/buildstamp ] || return

	head -n1 /etc/buildstamp \
		| cut -d' ' -f2-
}

# get_platform
get_platform()
{
	# FIXME: product_name is not a reliable key

	# on Lonestar-AMD-5 it is "ThinkPad Edge E455"
	# on Lonestar-AMD-3 it is "ThinkPad E455"

	# on Gordon-AMD-2 it is "ThinkPad Edge E555"
	# on Gordon-AMD-3 it is "ThinkPad E555"

	#local file=/sys/class/dmi/id/product_name
	local file=/sys/class/dmi/id/product_version

	if [ -r "$file" ]; then
		cat "$file"
	else
		echo "unknown"
		return 1
	fi
}

# get_devices
get_devices()
{
	lspci -n | cut -d' ' -f2,3 | tr -d ' :'
}

# get_bios_version
get_bios_version()
{
	cat /sys/class/dmi/id/bios_version | cut -b1-3
}
