#!/usr/bin/bash
trap '[ -d "$tempdir" ] && rm -rf "$tempdir"' EXIT INT

# TODO: -c takes a comma separated list or file?
# TODO: allow for user to specify CONFIGS ^^^ ?
# TODO: move the undo the p setting to map_configs_to_array
# TODO: Fix ERROR: message so it only shows when the file is being deleted

DEBUG=false

# global definitions
CONFIG=
priority_file=
ORDER=
cfgvariants=
toplevels=
subdirs=
rows=
columns=
configmap=
cfgs=
cfgs_base=
weightorig=
numorder=
longheader=
weightorig=
weight=
declare -A toplevel_order

tempdir=$(mktemp -d)

whatcouldgowrong() {
	echo ""
	echo "usage: evaluate_configs [-c CONFIG] [-d] [-j] [ -p priority_file] [-f]"
	echo ""
	echo "      -c CONFIG          Evalulate specific CONFIGs (file or csl)"
	echo "      -d                 Enable debug"
	echo "      -p priority.file   Specify a priority.file (no default)"
	echo "      -j                 Evaluate common directory"
	echo "      -f                 Evaluate CONFIGs"
	echo ""
	echo "examples)"
	echo ""
	echo "To show the status of CONFIG_HEADER_TEST in ARK,"
	echo "	./evaluate_configs -p priority.rhel -c CONFIG_HEADER_TEST"
	echo ""
	echo "To fix all the CONFIGS in Fedora,"
	echo "  ./evaluate_configs -p priority.fedora -f"
	echo ""
	echo "To fix only CONFIG_HEADER_TEST in RHEL,"
	echo "  ./evaluate_configs -p priority.rhel -c CONFIG_HEADER_TEST -f"
	echo ""
	echo "and commit the resulting changes."
	echo ""
	echo "To fix the common directory entries,"
	echo " ./evaluate_configs -j"
	echo ""
	exit 1
}

# Get a list of the config-variants
get_cfgvariants() { # uses priority_file
	local configvariant
	local cfgvariant

	# The priority files have a config-variant, followed by a hierarchy of
	# directories to examine for that config level.  The directories have
	# '-' instead of '/'.
	#
	# For example,
	#
	# ppc64le-debug=generic:generic-powerpc:debug:debug-powerpc
	#

	while read -r configvariant
	do
		# ignore any line with whitespace
		test -z "$configvariant" && continue
		# ignore any line beginning with a #
		[[ "$configvariant" == \#* ]] && continue
		# ignore any line beginning with ORDER
		[[ "$configvariant" == ORDER* ]] && continue
		# ignore any line beginning with EMPTY
		[[ "$configvariant" == EMPTY* ]] && continue

		# -debug variants must include the base variant
		# does the priority file contain a debug variant?
		cfgvariant=$(echo "$configvariant" | cut -d "=" -f 1)
		if grep -q "$cfgvariant-debug" "$priority_file"; then
			# if it does, skip this variant and only use -debug
			continue
		fi

		# if this variant has a -debug, remove the -debug
		cfgvariant=$(echo "$cfgvariant" | awk -F "-debug" ' { print $1 } ')

		# output "cfgvariant | configorder"
		echo "$cfgvariant | $(echo "$configvariant" | cut -d "=" -f 2 | tr : " " )"
	done < $priority_file
}

# Find top level dirs for each ORDER. These are normally just debug and config.
get_toplevel_dirs() { # uses cfgvariants
	local cfg
	local cfgvariant

	# anything with a dash(-) in it is a subdir
	echo "$cfgvariants" | while read -r cfgvariant
	do
		cfg=$(echo "$cfgvariant" | cut -d "|" -f 2)
		for i in $cfg
		do
			echo "$i" | grep -v "-"
		done
	done | sort -u | tr '\n' ' '
}

# For each top level count subdirs and find max subdirs for each top level
get_subdirs() { # uses $cfgvariants and $toplevels
	local max
	local LINE
	local count
	local toplevel

	for toplevel in $toplevels
	do
		max=0
		count=0
		OLDIFS=$IFS; IFS=$'\n'; for LINE in $cfgvariants
		do
			LINE=$(echo "$LINE" | cut -d "|" -f 2)
			count=0
			IFS=$' '; for i in $LINE
			do
				echo "$i" | grep -q -v $toplevel && continue
				count=$(echo "$i" | awk -F "-" '{print NF-1}')
				[ "$max" -lt "$count" ] && max="$count"
			done
		done
		IFS=$OLDIFS
		echo "$toplevel subdirs $((max + 1))"
	done
}

# Walk through cfgvariants and give each toplevel dir an ordering number.
# This number is later used to insert EMPTY tags at correct place.
create_toplevel_order() { # uses toplevel_order

while read -r cfgvariant
do
	local i
	local max
	local order
	local topname

	LINE=$(echo "$cfgvariant" | cut -d "|" -f 2)

	for i in $LINE; do
		topname="${i%%-*}"
		order=${toplevel_order[$topname]}
		if [ -z "$order" ]; then
			max=$(echo "${toplevel_order[@]}" | wc -w)
			max=$((max + 1))
			toplevel_order[$topname]=$max
			$DEBUG && echo "toplevel_order[$topname] = $max"
		fi
	done
done <<< "$cfgvariants"
}

# For each config-variant, find missing sub-directories and mark them as "EMPTY"
# This is very helpful for stage 3.
fix_config_variants() { # uses $toplevels, $subdirs, $cfgvariants, $toplevel_order

for toplevel in $toplevels
do
	local subdircnt
	local linenum
	local cfgvariant
	local LINE
	local count
	local oldentry
	local newentry
	local found
	local dashcount
	local new
	local topname
	local new_topname

	subdircnt=$(echo "$subdirs" | grep "$toplevel" | awk -F "subdirs" ' { print $2 } ')
	linenum=0
	echo "$cfgvariants" | while read -r cfgvariant
	do
		linenum=$((linenum + 1))
		# this seems strange to immediately reset cfgvariant but we
		# want the value from the file, not the one in memory.  The
		# value in the file may have been modified by a previous
		# toplevel.
		cfgvariant=$(sed "${linenum}q;d" "$tempdir"/cfgvariants)

		LINE=$(echo "$cfgvariant" | cut -d "|" -f 2)

		$DEBUG && echo "LINE=$LINE"
		# get the actual number of subdirs
		count=$(for i in $LINE
		do
			echo "$i" | grep -q -v "$toplevel" && continue
			echo "$i" | awk -F "-" '{print NF-1}'
		done | wc -l)

		[ -z "$count" ] && continue
		$DEBUG && echo "count=$count"

		# if the number of subdirs is the same, then bail
		[ "$count" -eq "$subdircnt" ] && continue

		$DEBUG && echo "missing entries LINE=$LINE"
		oldentry=$(for i in $LINE
		do
			echo "$i" | grep -q "$toplevel" && echo "$i" | tr "\n" " "
		done| xargs)
		$DEBUG && echo "oldentry=|$oldentry|"

		# Find the missing entry
		found=$(for i in $oldentry
		do
			dashcount=$(echo "$i" | awk -F "-" '{print NF-1}')
			dashcount=$((dashcount + 1))
			echo $dashcount
		done | tr "\n" " ")
		$DEBUG && echo "found=$found"

		# build the missing entry
		count=1
		newentry=$(for i in $(seq 1 "$subdircnt")
		do
			if echo "$found" | grep -q "$i"; then
				echo "$oldentry" | cut -d " " -f "$count"
				count=$((count + 1))
			else
				echo "${toplevel}-EMPTY$((i - 1))"
			fi
		done | tr "\n" " " | xargs)
		$DEBUG && echo "newentry=|$newentry|"

		# insert the missing entry
		if echo "$LINE" | grep -q "$toplevel"; then
			new=${cfgvariant//$oldentry/$newentry}
		else
			# Find out toplevel name of new EMPTY entries and use
			# toplevel_order to figure out where to insert those.
			found=0
			new_topname="${newentry%%-*}"
			new="$(echo "$cfgvariant" | cut -d "|" -f 1)|"
			LINE=$(echo "$cfgvariant" | cut -d "|" -f 2)

			for i in $LINE; do
				topname="${i%%-*}"
				if [ $found -eq 1 -o ${toplevel_order[$topname]} -lt ${toplevel_order[$new_topname]} ]; then
					new="$new $i"
				else
					found=1
					new="$new $newentry $i"
				fi
			done
			if [ $found -eq 0 ]; then
				new="$new $newentry"
			fi
		fi

		$DEBUG && echo "REPLACED:"
		$DEBUG && echo "orig=$cfgvariant"
		$DEBUG && echo " new=$new"

		sed -i "${linenum}s/${cfgvariant}/${new}/" "$tempdir"/cfgvariants

		$DEBUG && echo "----------------------------"
	done
done
}

# create a configmap
get_configmap() { # uses $ORDER and $cfgvariants
	local configvariant
	local arch
	local _configorder
	local configorder
	local order

	for order in $ORDER
	do
		# jforbes: pending-fedora can be dropped.  It should be empty
		# most of the time.
		[ "$order" == "pending-fedora" ] && continue

		echo "$cfgvariants" | while read -r configvariant
		do
			arch=$(echo "$configvariant" | cut -d "|" -f 1)
			_configorder=$(echo "$configvariant" | cut -d "|" -f 2 | tr : " " )
			configorder=$(for c in $_configorder
			do
				echo -n "${order}-${c} "
			done; echo "")

			echo "${order}-$arch | $configorder"
		done
	done
}

# pretty output
output_pretty_cfgs() { # uses cfgs and configmap, rows, and columns
	local x
	local index
	local _configmap

	index=0
	for x in $(seq 1 $rows)
	do
		[ "$x" == 1 ] && echo "legend" "$1"
		_configmap=$(echo "$configmap" | sed "${x}q;d" | cut -d "|" -f 1)
			echo "$_configmap ${cfgs[@]:$index:$columns}"
		index=$((index + columns))
	done | column -t
}

# helper function to remove a CONFIG file
delete_file() {
	local position
	local configentry

	position=$1
	configentry=$2
	# if the entry doesn't exist, decrease weight by 1
	weight[$position]=$((weight[$position] - 1))
	if [ "${weight[$position]}" -le 0 ]; then
		if [ -e "$configentry" ]; then
			$DEBUG && echo "| Deleting $configentry ${weight[$position]})" || echo "| Deleting $configentry"
			rm -f "$configentry"
		fi
	else
		$DEBUG && echo "| Not deleted.  Required by other config variants (${weight[$position]})"
	fi
}

# find duplicate entries
fix_broken_arches() { # uses ORDER, crows, columns, and configmap
	local row
	local x
	local y
	local value
	local _value
	local char
	local position
	local curr

	# See comment about weight in create_output_header()
	weight=("${weightorig[@]}")

	# This search is handled differently than
	# output_pretty_cfgs().  A string is created that
	# is only for the specific cfg-variant (row * numorder
	# long).  This string is easier to evaluate.
	for row in $(seq 0 $((crows - 1)))
	do
		# construct the string of values to view
		value=$(for order in $(seq 0 $((numorder - 1)))
		do
			index=$(((order * (crows * columns)) + (row * columns)))
			echo -n "${cfgs[@]:$index:$columns} "
		done
		echo "")
		$DEBUG && echo "row=$row $value"

		# check to see if there is a config setting conflict
		_value=$(echo "$value" | tr -d " X-")
		if echo "$_value" | grep -q "yy\|mm\|nn"; then
			# go through the value string, ex) y-y-Xm-,
			# and find the characters that match the
			# previous character.
			curr="p"
			position=0
			# use value here as each character is
			# separated by a space
			for char in $value
			do
				index=$(( ((crows * columns) * (position / columns)) + (row * columns) + (position % columns) ))
				# sed is 1-based so add 1 to x and y
				y=$(((index / columns) + 1))
				# configmap contains the cfgvariant and a
				# pipe (+3), and needs to be 1-based
				x=$(((index % columns) + 4))
				$DEBUG && echo "($x,$y) $index"

				configentry="$(echo "$configmap" | sed "${y}q;d" | cut -d " " -f "$x" | tr "-" "/")/$CONFIG"
				cfgvariant=$(echo "$configmap" | sed "${y}q;d" | cut -d " " -f 1)

				# if this, char, is the same as curr then
				# there is a conflict and char needs to
				# be changed.
				if [ "$char" == "$curr" ]; then
					echo ""
					echo "ERROR: (hierarchy) $configentry : superseding value has $curr."
					echo "|$CONFIG ($cfgvariant)"
					printf "|$longheader\n|$value" | column -t
					$DEBUG && echo "position=$position | $(echo "$value" | cut -d " " -f $((position + 1)) ) | weight=${weight[$position]}"

					# See comment about weight in
					# create_output_header()
					delete_file "$position" "$configentry"
					break
				fi
				case "$char" in
				'-')
					;;
				'X')
					# See comment about weight in
					# create_output_header()
					delete_file "$position" "$configentry"
					;;
				* )
					curr=$char
					;;
				esac
				position=$((position + 1))
			done
		else
			# still have to examine this string because it may
			# contain "X", which has to be accounted for in
			# the weights.
			echo "$value" | grep -q "X" || continue
			position=0
			for char in $value
			do
				if [ "$char" == 'X' ]; then
					index=$(( ((crows * columns) * (position / columns)) + (row * columns) + (position % columns) ))
					# sed is 1-based so add 1 to x and y
					y=$(((index / columns) + 1))
					# configmap contains the cfgvariant and
					# a pipe (+3), and needs to be 1-based
					x=$(((index % columns) + 4))
					$DEBUG && echo "($x,$y) $index"

					configentry="$(echo "$configmap" | sed "${y}q;d" | cut -d " " -f "$x" | tr "-" "/")/$CONFIG"
					cfgvariant=$(echo "$configmap" | sed "${y}q;d" | cut -d " " -f 1)
					# See comment about weight in
					# create_output_header()
					delete_file "$position" "$configentry"
				fi
				position=$((position + 1))
			done
		fi

	done
}

# compare the common, fedora, and rhel configs.
# By default this function uses the priority.common file
fix_common() { # uses cfgs, CONFIG, and ORDER
	local index
	local value
	local _value
	local x
	local y
	local configentry
	local _configentry
	local order

	# the priority.common array is
	#	common configs
	#	rhel configs
	#	fedora configs
	for index in $(seq 0 $(((crows * columns) - 1)))
	do
		# this string is the concatenation of the
		# common, rhel, and fedora config values
		value=$(for order in $(seq 0 $((numorder -1)))
		do
			echo -n "${cfgs[$(( (order * crows * columns) + index))]}"
		done
		echo "")

		# It doesn't matter what common is set to so
		# trim it off.
		_value="${value:1}"
		if echo "$_value" | grep -q "yy\|mm\|nn"; then

			# set _value to just y|m|n
			_value="${_value:1}"

			# create a long array to see if the change is valid
			checkvalue=$(for order in $(seq 0 $((numorder -1)))
			do
				step=$(( order * crows * columns))
				# this seems weird but it rounds off to columns
				row=$(( (step + index) / columns * columns))
				echo -n "${cfgs[@]:$row:$columns} "
			done; echo "")

			$DEBUG && echo "checkvalue=$checkvalue"

			IFS=', ' read -r -a checkvalue <<< "$checkvalue"
			_index=$((index % columns))

			for order in $(seq 1 $((numorder -1)))
			do
				checkvalue[$((( order * columns ) + _index))]='-'
			done
			$DEBUG && echo "updated checkvalue=${checkvalue[@]}"

			# set the common entry to _value, so that an analysis
			# can be run on the other entries
			checkvalue[$_index]="$_value"

			count=0
			cfgvalue=${checkvalue[0]}
			warning=false
			for i in ${checkvalue[@]}
			do
				echo "$i" | grep -q 'm\|n\|y' && cfgvalue=$i
				if [ $count == $_index ]; then
					if [ "$cfgvalue" != "$_value" ]; then
						$DEBUG && echo "$CONFIG override will not work."
						warning=true
						break;
					fi
					_index=$((_index + columns))
				fi
				count=$((count + 1))
			done

			$warning && break

			echo "$CONFIG found a match where common should be set."

			# sed is 1-based so add 1 to x and y
			y=$(((index / columns) + 1))
			# configmap contains the cfgvariant and a
			# pipe (+3), and needs to be 1-based
			x=$(((index % columns) + 4))
			$DEBUG && echo "($x,$y) $index"

			# remove the existing rhel and fedora configs
			configentry="$(echo "$configmap" | sed "${y}q;d" | cut -d " " -f "$x" | tr "-" "/")/$CONFIG"
			for order in $ORDER
			do
				[ "$order" == "common" ] && continue
				_configentry=${configentry//common/$order}
				[ -e "$_configentry" ] && rm -f "$_configentry"
			done

			# create a new common config
			echo "$_value" in "$configentry"
			case "$_value" in
			m)
				echo "${CONFIG}=m" > "$configentry"
				;;
			y)
				echo "${CONFIG}=y" > "$configentry"
				;;
			n)
				echo "# $CONFIG is not set" > "$configentry"
				;;
			esac
		fi
	done
}

# Check that ccolumns is consistent
debug_cfgvariants() { # uses $cfgvariants and sets crows and ccolumns
	local LINE

	crows=$(echo "$cfgvariants" | wc -l)

	ccolumns=$(echo "$cfgvariants" | while read -r LINE
	do
		LINE=$(echo "$LINE" | cut -d "|" -f 2)
		echo "$LINE" | wc -w
	done | sort -u)

	# Error check columns
	if [ "$(echo "$ccolumns" | wc -l)" != "1" ]; then
		echo "ERROR in parser.  There were multiple length columns found."
		echo "$ccolumns"
		exit 1
	fi
}

# Create an output header, a fancy long header for fix_broken_arches, and the
# weights
create_output_header() { # uses $ORDER, $configmap, and sets output_header
			 # and weightorig

	local order
	local dir
	local convert
	local f
	local configline

	# We know that the configmap now contains correct sized entries for
	# each arch.  The arch doesn't really matter and we just need the
	# information to make a header.
	order=$(echo "$ORDER" | cut -d " " -f 1)
	configline=$(echo "$configmap" | head -1 | cut -d "|" -f 2 | sed "s/${order}-//g")
	for dir in $configline
	do
		convert=false
		if echo "$dir" | grep -q "-"; then
			if echo "$dir" | grep -q "EMPTY0"; then
				dir=$(echo "$dir" | awk -F "-EMPTY0" ' { print $1 } ')
				convert=true
			fi
		else
			convert=true
		fi

		! $convert && continue

		# get the first letter of each word
		f=$(echo "$dir" | head -c 1)
		$DEBUG && echo "directory $dir entries will be converted to $f"
		configline=${configline//$dir/$f}
	done

	# Go through the configline and convert the directory names into header
	# names For example,
	#    generic generic-x86 generic-x86-x86_64 generic-EMPTY3 debug-EMPTY0 debug-EMPTY1 debug-EMPTY2
	# will be converted to
	#    g ga1 ga2 ga3 d da1 da2
	output_header=$(for dir in $configline
	do
		# convert dirs with no dashes to the same thing
		if ! echo "$dir" | grep -q "-"; then
			echo "$dir"
			continue
		fi
		f=$(echo "$dir" | cut -d "-" -f 1)
		# convert g-x86 to ga, and g-x86-x86_64 to ga2, etc.
		if echo "$dir" | grep -q "EMPTY"; then
			numempty=$(echo "$dir" | awk -F "EMPTY" ' { print $2 } ')
			if [ "$numempty" -eq 0 ]; then
				echo "$f"
			else
				echo "${f}a${numempty}"
			fi
		else
			numdashes=$(echo "$dir"| grep -o "-" | wc -l)
			echo "${f}a${numdashes}"
		fi
	done | tr "\n" " ")

	# create a weightorig array that contains the weights of change for
	# each directory.  This is useful for the -f option display
	for entry in $output_header
	do
		if echo "$entry" | grep -q 'a'; then
			_weightorig+=(1)
		else
			_weightorig+=("$crows")
		fi
	done

	# It is possible (and valid) to have an subdir arch followed by
	# a debug entry.  The -f checker would have flagged this and
	# removed the file.  As a solution there is a weight associated
	# with each entry's CONFIG file.  A debug or generic entry has
	# a weight equal the number of columns, and the arch entries all
	# have a weight of one.  The -f tracker subtracts one for each "hit"
	# and only removes the file if the weight is 1.

	weightorig=""
	longheader=""
	for order in $(seq 1 $numorder)
	do
		weightorig="${weightorig[@]} ${_weightorig[@]}"
		longheader="${longheader}${output_header}"
	done
	IFS=', ' read -r -a weightorig <<< "$weightorig"
}

# initialize the array to '-' (undefined) and 'X' (not present/EMPTY)
init_cfgs() { #uses cfgs, rows, and columns
	unset cfgs
	eval "$(eval echo "cfgs[{1..$((rows * columns))}]='-'\;")"
	# the -'s can be a problem when being parsed by other commands.  I
	# tried using +, o, ., X, etc. but none of the output was as clear as
	# a dash.  Initialize the 0th element to an unused letter.  If still
	# 'p' it can be changed back later on.
	cfgs[0]=p

	# set EMPTY configs to X
	for row in $(seq 0 $((rows - 1)))
	do
		index=$((row * columns))
		num=0
		for entry in $(echo "$cfgvariants" | sed "$(((row % crows) + 1))q;d" | cut -d "|" -f 2)
		do
			echo "$entry" | grep -q EMPTY && cfgs[$((index + num))]='X'
			num=$((num + 1))
		done
	done
	cfgs_base=("${cfgs[@]}")
}

# reset the configs to default
reset_cfgs() {
	unset cfgs
	cfgs=("${cfgs_base[@]}")
}

# map the CONFIG files to the array
map_configs_to_array() { #uses CONFIG, configmap, cfgs

	local LINE
	local contents
	local _LINE
	local row
	local cols
	local col

	for LINE in $(find ./ -name $CONFIG -printf '%P\n' | awk -F "/$CONFIG" ' { print $1 } ')
	# loop through the CONFIG files
	do
		$DEBUG && echo "+-------------------"
		$DEBUG && echo "found: $LINE"

		contents=$(grep "^# $CONFIG is not set\|^$CONFIG=" "$LINE"/"$CONFIG")
		case $contents in
		"# $CONFIG is not set")
			contents=n
			;;
		"${CONFIG}=y")
			contents=y
			;;
		"${CONFIG}=m")
			contents=m
			;;
		*)
			echo "$LINE/$CONFIG has a strange entry ... skipping"
			return 1
			break;;
		esac

		$DEBUG && echo "contents=$contents"

		_LINE=$(echo "$LINE" | tr "/" "-")
		$DEBUG && echo "_LINE=$_LINE"
		# set each cfg to $contents
		OLDIFS=$IFS; IFS=$'\n'; for rowandcol in $(echo "$configmap" | grep -n " $_LINE ")
		do
			row=$(echo "$rowandcol" | cut -d ":" -f 1)
			# grep is 1 based and we need a 0 based number
			row=$((row - 1))
			cols=$(echo "$rowandcol" | cut -d "|" -f 2)
			$DEBUG && echo "row=$row"
			$DEBUG && echo "cols=$cols"

			col=$(echo "$cols" | awk -F "$_LINE" ' { print $1 }' | wc -w)
			$DEBUG && echo "($col, $row) = $contents"
			# convert the (col,row) to an index in the array
			$DEBUG && echo "setting element $(($((row * columns)) + col)) = $contents"
			# set the config
			cfgs[$(($((row * columns)) + col))]=$contents
		done
		IFS=$OLDIFS
	done

	# undo the 'p' setting of the initial element
	# (setting to 'p' done in init_cfgs)
	[ "${cfgs[0]}" == "p" ] && cfgs[0]="-"

	return 0
}

generate_finalconfiglist() {
	awk '
		/is not set/ {
			split ($0, a, "#");
			split(a[2], b);
			print b[1] ;
		}
		/=/ {
			split ($0, a, "=");
			print a[1];
		}
	' *.config | sort -u >> .finalconfiglist
}

find_dead_configs() {
	echo > .finalconfiglist
	echo > .configlist

	grep -q "rhel" flavors && (cd ..; make rh-configs) && generate_finalconfiglist
	grep -q "fedora" flavors && (cd ..; make fedora-configs) && generate_finalconfiglist
	sort -o .finalconfiglist -u .finalconfiglist

	find ./ -name CONFIG_* | sed 's!.*/!!' | sort -u > .configlist

	echo "These CONFIGS defined in redhat/configs but not the final .configs have been deleted:"
	comm .configlist .finalconfiglist -2 -3 | while read FILENAME
	do
		echo $FILENAME
		find ./ -name $FILENAME | xargs rm -f
	done

	rm -f .configlist .finalconfiglist
}

#
#
# MAIN
#
#

# PROCESS ARGUMENTS
FINDFIXES=false
FIXCOMMON=false
configs=
while getopts "c:dDfhjp:" opt; do
	case ${opt} in
	c )
		configs=$OPTARG
		;;
	d )
		DEBUG=true
		;;
	D )
		find_dead_configs
		exit 0
		;;
	f )
		# Find fixes per config-variant
		FINDFIXES=true
		;;
	h )
		whatcouldgowrong
		;;
	j )
		# jforbes mode
		priority_file=priority.common
		FIXCOMMON=true
		;;
	p )
		# Get the high level order from the priority file
		priority_file=$OPTARG
		;;
	*)
		whatcouldgowrong
		;;
	esac
done

$DEBUG && echo "priority_file=$priority_file"
$DEBUG && echo "configs=$CONFIG"
$DEBUG && echo "FINDFIXES=$FINDFIXES"
$DEBUG && echo "FIXCOMMON=$FIXCOMMON"

# Do some simple error checking
if [ -z "$priority_file" ]; then
	echo "Specify a priority.* file"
	whatcouldgowrong
fi

# if configs is not set then do all CONFIGS
if [ -z "$configs" ]; then
	find ./ -name "CONFIG*" -type f -printf "%f\n" | sort -u > "$tempdir"/CONFIGS
	configs=$tempdir/CONFIGS
fi

# if configs is still not set, then parse the argument provided
if [ ! -e "$configs" ]; then
# assume the user is smart enough to specify CONFIGs
	for config in ${configs//,/ }
	do
		# Allow users to specify configs without CONFIG_
		if ! echo "$config" | grep -q CONFIG; then
			config="CONFIG_${config}"
		fi
		echo "$config" >> "$tempdir"/CONFIGS
	done
	configs=$tempdir/CONFIGS
else
	# if the file exists just copy it
	[ ! -e "$tempdir"/CONFIGS ] && cp "$configs" "$tempdir"/CONFIGS
fi

ORDER=$(grep "^ORDER" "$priority_file"| cut -d "=" -f 2)

# STEP 1.  Parse the priority file

cfgvariants=$(get_cfgvariants)
$DEBUG && echo "----------------------------------------"
$DEBUG && echo "cfgvariants:"
$DEBUG && echo "$cfgvariants"
$DEBUG && echo "----------------------------------------"
toplevels=$(get_toplevel_dirs "$cfgvariants")
$DEBUG && echo "Top level directories in priority file: $toplevels"
subdirs=$(get_subdirs)
$DEBUG && echo "Top-level sub-directories:"
$DEBUG && echo "$subdirs"

# Create ordering for toplevel dirs
create_toplevel_order

# Add EMPTY entries for each missing subdirectory level in the config
# variants
echo "$cfgvariants" > "$tempdir"/cfgvariants
fix_config_variants
$DEBUG && echo ""
$DEBUG && echo ""
$DEBUG && echo "Fixed: cfgvariants"
$DEBUG && cat "$tempdir"/cfgvariants

# Reset cfgvariants to new values with EMPTYs.
# cfgvariants now contains the config-variant data with EMPTY subdirs.
cfgvariants=$(cat "$tempdir"/cfgvariants)
crows=
ccolumns=
debug_cfgvariants
$DEBUG && echo "For the config-variants there are $crows rows and $ccolumns columns."

# STEP 2.  Now that we have fixed the list of config variants, create a config
# map that contains all entries wrt the ORDER specified in the priority file.

numorder=$(echo "$ORDER" | wc -w)
# jforbes: pending-fedora can be dropped.  It should be empty
# most of the time.
echo "$ORDER" | grep -q "pending-fedora" && numorder=$((numorder -1))

# configmap is the list of config-variants used for displaying and analyzing
# the CONFIGs.
configmap=$(get_configmap)
$DEBUG && echo " "
$DEBUG && echo "The configmap is:"
$DEBUG && echo "$configmap"
$DEBUG && echo " "

# STEP 3.  Create an array and header to hold the configmap data.

rows=$(echo "$configmap" | wc -l)
columns=$(echo "$configmap" | head -1 | cut -d "|" -f 2 | wc -w)
$DEBUG && echo "There are $rows rows and $columns columns in the configmap."

create_output_header # sets output_header
$DEBUG && echo "output_header=|$output_header|"
$DEBUG && echo "longheader=|$longheader|"
$DEBUG && echo "output_header has weights ${weightorig[@]}"

# create the cfgs array and initialize it to '-' (not found)
init_cfgs

if $FINDFIXES; then
	while read -r CONFIG
	do
		reset_cfgs
		map_configs_to_array || continue

		fix_broken_arches "$output_header"
	done < "$tempdir"/CONFIGS
	exit
fi

if $FIXCOMMON; then
	while read -r CONFIG
	do
		reset_cfgs
		map_configs_to_array || continue
		fix_common
	done < "$tempdir"/CONFIGS
	exit
fi

# only display the configs
	while read -r CONFIG
	do
		reset_cfgs
		map_configs_to_array || continue
		echo ""
		echo "$CONFIG"
		output_pretty_cfgs "$output_header"
	done < "$tempdir"/CONFIGS
exit
