#!/bin/sh

TRUNK=../..

all=0
valg=0
global_args="-c design/fab_author=TEST -c rc/quiet=1 -c rc/default_pcb_file={} -c rc/default_font_file=./default_font"
test_announce=0
verbose=0
CONVERT=convert

if test -z "$pcb_rnd_bin"
then
	pcb_rnd_bin="$TRUNK/src/pcb-rnd"
fi


fmt_args=""

need_convert()
{
	if test -z "`$CONVERT | grep ImageMagick`"
	then
		echo "WARNING: ImageMagick convert(1) not found - bitmap compare will be skipped."
	fi
}

set_fmt_args()
{
	case "$fmt" in
		bboard) need_convert; ext=.bbrd.png ;;
		nelma) ext=.nelma.em ;;
		bom) ext=.bom ;;
		dsn) ext=.dsn ;;
		IPC-D-356) ext=.net;;
		ps)
			ext=.ps
			fmt_args="-c plugins/draw_fab/omit_date=1"
			;;
		eps)
			ext=.eps
#			fmt_args="-c plugins/draw_fab/omit_date=1"
			;;
		XY) ext=.xy ;;
		openscad)
			ext=.scad
			fmt_args="--silk"
			;;
		png)
			need_convert
			fmt_args="--dpi 1200"
			ext=.png
			;;
		gerber)
			fmt_args="--cross-sect -c plugins/draw_fab/omit_date=1"
# multifile: do not set ext
			;;
		remote)
			ext=.remote
			;;
		svg)
			ext=.svg
			;;
		fidocadj)
			ext=.fcd
			;;
	esac
}

move_out()
{
	local raw_out="$1" final_out="$2" n

# remove variable sections
	case "$fmt" in
		dsn) sed -i 's/[(]host_version[^)]*[)]/(host_version "<version>")/g' $raw_out ;;
		bom|XY) sed -i "s/^# Date:.*$/# Date: <date>/" $raw_out ;;
		IPC-D-356)
			sed -i '
				s/^C  File created on .*$/C  File created on <date>/
				s/^C  IPC-D-356 Netlist generated by.*$/C  IPC-D-356 Netlist generated by <version>/
			' $raw_out ;;
		nelma)
			sed -i 's@/[*] Made with PCB Nelma export HID [*]/.*@/* banner */@g' $raw_out ;;
		gerber)
			sed -i '
				s/^G04 CreationDate:.*$/G04 CreationDate: <date>/
				s/^G04 Creator:.*$/G04 Creator: <version>/
			' $raw_out.*.gbr
# do not save or compare the csect yet
			rm $raw_out.*csect*.gbr
			;;
		ps)
			sed -i '
				s@%%CreationDate:.*@%%CreationDate: date@
				s@%%Creator:.*@%%Creator: pcb-rnd@
				s@%%Version:.*@%%Version: ver@
				s@^[(]Created on.*@(Created on date@
			' $raw_out
			;;
	esac

# move the output file(s) to their final subdir (for multifile formats) and/or
# compress them (for large text files)
	case "$fmt" in
		bboard)
			mv ${raw_out%%.bbrd.png}.png $final_out
			;;
		gerber)
			mkdir -p $final_out.gbr
			mv $raw_out.*.gbr $final_out.gbr
			mv $raw_out.*.cnc $final_out.gbr 2>/dev/null
			;;
		nelma)
			mv $raw_out $final_out
			# do not test the pngs for now
			rm -f ${raw_out%%.em}*.png
			;;
		remote|ps)
			gzip $raw_out
			mv $raw_out.gz $final_out.gz
			;;
		*)
			# common, single file output
			if test -f "$raw_out"
			then
				mv $raw_out $final_out
			fi
			;;
	esac
}

cmp_fmt()
{
	local ref="$1" out="$2" n bn otmp
	case "$fmt" in
		png)
			if test ! -z "$CONVERT"
			then
				bn=`basename $out`
				res=`compare "$ref" "$out"  -metric AE  diff/$bn 2>&1`
				case "$res" in
					*widths*)
						otmp=$out.599.png
						$CONVERT -crop 599x599+0x0 $out  $otmp
						res=`compare "$ref" "$otmp" -metric AE  diff/$bn 2>&1`
						;;
				esac
				test "$res" -lt 8 && rm diff/$bn
				test "$res" -lt 8
			fi
			;;
		bboard)
			if test ! -z "$CONVERT"
			then
				bn=`basename $out`
				res=`compare "$ref" "$out"  -metric AE  diff/$bn 2>&1`
				test "$res" -lt 8 && rm diff/$bn
				test "$res" -lt 8
			fi
			;;
		gerber)
			for n in `ls $ref.gbr/*.gbr $ref.gbr/*.cnc 2>/dev/null`
			do
				bn=`basename $n`
				diff -u "$n" "$out.gbr/$bn"
			done
			;;
		ps)
			zcat "$ref.gz" > "$ref"
			zcat "$out.gz" > "$out"
			diff -u "$ref" "$out" && rm "$ref" "$out"
			;;
		*)
			# simple text files: byte-to-byte match required
			diff -u "$ref" "$out"
			;;
	esac
}

run_test()
{
	local fn="$1" valgr res res2

	if test "$valg" -gt 0
	then
		valgr="valgrind -v --log-file=$fn.vlog"
	fi

	if test "$verbose" -gt 0
	then
		echo "=== Test: $fmt $fn ==="
	fi

	# run and save stderr in file res2 and stdout in variable res
	res2=`mktemp`
	res=`$valgr $pcb_rnd_bin -x "$fmt" $global_args $fmt_args "$fn" 2>$res2`

	# special case error: empty design is not exported; skip the file
	if test ! -z "$res"
	then
		case "$res" in
			*"export empty board"*) rm $res2; return 0 ;;
		esac
	fi

	# print error messages to the log
	sed "s/^/[pcb-rnd:stderr]  /" < $res2 >&2
	rm $res2

	base=${fn%%.pcb}
	base=${base%%.lht}
	ref_fn=ref/$base$ext
	fmt_fn=$base$ext
	out_fn=out/$base$ext

	move_out "$fmt_fn" "$out_fn"
	cmp_fmt "$ref_fn" "$out_fn"
}

while test $# -gt 0
do
	case "$1"
	in
		--list)
			$pcb_rnd_bin -x nonexistentexporter 2>&1 | sed '
				/available/ { s/^[^:]*: *//; s/ /\n/g; q; }
				{ d }
			'
			exit 0;;
		-t) test_announce=1;;
		-f|-x) fmt=$2; shift 1;;
		-b) pcb_rnd_bin=$2; shift 1;;
		-a) all=1;;
		-V) valg=1;;
		-v) verbose=1;;
		*)
			if test -z "$fn"
			then
				fn="$1"
			else
				echo "unknown switch $1; try --help" >&2
				exit 1
			fi
			;;
	esac
	shift 1
done

if test -z "$fmt"
then
	echo "need a format" >&2
fi

set_fmt_args

if test "$test_announce" -gt 0
then
	echo -n "$fmt: ... "
fi

bad=""
if test "$all" -gt 0
then
	for n in `ls *.lht *.pcb 2>/dev/null`
	do
		run_test "$n" || bad="$bad $n"
	done
else
	run_test "$fn" || bad="$bad $n"
fi

if test ! -z "$bad"
then
	if test "$verbose" -gt 0
	then
		echo "$fmt: ... BROKEN: $bad"
	else
		echo "$fmt: ... BROKEN"
	fi
	exit 1
else
	echo "ok"
	exit 0
fi


