#!/bin/sh -e

. /lib/rcscripts/sh/string.sh

SELF=${0##*/}
TAG="$SELF[$$]"
LOCKF=$SELF
TMP_FILE=
_LFD=/var/lock/resolution_update
LOCKFPATH="$_LFD/$LOCKF"

cleanup() {
	[ -z "$TMP_FILE" ] || rm -f $TMP_FILE
}

lock_file_validate() {
	local _f=lock_file_validate
	[ $# -eq 2 ] || error "$0: $_f: missing argument"

	local __lf

	__lf=${1##*/}
	[ "$__lf" = "$1" ] ||
		warning "$0: $_f: invalid file name; stripped to '$__lf'"
	__lf=${__lf%.lock}
	[ "$__lf" = "$1" ] ||
		warning "$0: $_f: invalid file name; stripped to '$__lf'"
	eval $2="$_LFD/$__lf.lock" ||
		 error "$0: $_f: can't evaluate '$2=$__lf'"
}

lock_file_remove()
{
	local _f=lock_file_remove _lf

	[ $# -eq 1 ] || error "$0: $_f: missing argument"

	lock_file_validate $1 _lf

	[ ! -e $_lf ] || {
		read _pid < $_lf ||
			warning "$0: $_f: read pid from $_lf failed"
		[ "$_pid" != $$ ] || rm -f $_lf
	}
}

unlock() {
	lock_file_remove "$LOCKF"
}

lock_file_create() {
	local _f=lock_file_create _lf

	[ $# -eq 1 ] || error "$0: $_f: missing argument"

	lock_file_validate $1 _lf

	[ -d $_LFD ] ||
		error "$0: $_f: missing directory $_LFD"

	pid2=$$
	exec 200>"$_lf"
	flock -x 200 || exit 1
	pid=$$
	echo $pid 1>&0
}

lock() {
	trap 'cleanup;unlock' EXIT QUIT INT TERM
	lock_file_create "$LOCKF"
}

bark() {
	logger -t $TAG -p warning "$*"
}

croak() {
	bark "$*"
	exit 1
}

### GLOBAL VARIABLES #####################################################

PHC="parhandclient --nocgi"
FOCUSWINDOW_DEFAULT=0.15,0.15:0.85,0.15:0.85,0.85:0.15,0.85

PARHAND_USR_ETC_DIR=/usr/etc/param
PARHAND_PROP_IMAGE=par_prop_image.conf
CONF_DIR=/etc/sysconfig
CONF_IMAGE_SOURCE=image_source.conf
TOURD_SERVICE=preset-tour.service

sysconfdir=/etc/sysconfig

### FUNCTIONS ##############################################################

safe_print() {
	local tempfile old_data d
	tempfile=$2.temp
	old_data=
	[ ! -f $2 ] || old_data=$(cat $2) || return 1
	[ "$old_data" = "$1" ] || {
		[ ! -f $2 ] || cp -p $2 $tempfile || return 1
		echo "$1" >$tempfile || return 1
		fsync $tempfile
		mv $tempfile $2 || return 1
		d=${2%/*}
		[ $d != $2 ] || d=.
		fsync $d
	}
}

safe_sed() {
	local new_data
	new_data=$(sed -r "$1" $2)
	safe_print "$new_data" $2
}

check_configuration_files() {
	[ -r $PARHAND_USR_ETC_DIR/$PARHAND_PROP_IMAGE ] ||
		croak "$PARHAND_USR_ETC_DIR/$PARHAND_PROP_IMAGE not found"
}

source_parts() {

	[ $# -ge 1 ] && [ "$1" ] ||
		croak "source_parts: missing mandatory parameter"

	local drop_file drop_files=/usr/share/resolution_update/resolution_update_dir.d/*
	for drop_file in $drop_files; do
		[ ! -f $drop_file ] || [ ! -x $drop_file ] || {
			local RESOLUTION_UPDATE_ACTION=$1
			local RESOLUTION_UPDATE_PAR1=$2
			local RESOLUTION_UPDATE_PAR2=$3
			. $drop_file || croak "Could not source $drop_file"
		}
	done
}


run_parts_deprecated() {

	[ $# -eq 3 ] && [ "$1" ] && [ "$2" ] && [ "$3" ] ||
		croak "run_parts_deprecated: wrong number of arguments"

	local drop_file drop_files=$1/*
	for drop_file in $drop_files; do
		[ ! -f $drop_file ] || [ ! -x $drop_file ] || {
			local RESOLUTION_UPDATE_COMMAND=$2
			local RESOLUTION_UPDATE_STREAM_IDS=$3
			. $drop_file || croak "Could not source $drop_file"
		}
	done
}

setup_capturemode_sensitive_data() {
	local cmprefix=/etc/image2d/cml do_reset=false cmfile streamid
	local streamids=

	for cmfile in $cmprefix*; do
		[ ! -f $cmfile ] || {
			streamid=${cmfile##$cmprefix}
			[ -z "$streamid" ] || {
				streamids="$streamids$streamid "
			}
			rm -f $cmfile
			do_reset=true
		}
	done

	[ $do_reset = false ] || {
		run_parts_deprecated /usr/share/resolution_update/resolution_update.d $START_COMMAND "$streamids"

		remove_groups Motion.M /etc/dynamic/motion.conf || :
	}
}

init_default_resolutions() {
	RESOLUTION_DEFAULT=$(res_finder $RES_FINDER_EXTRA_ARGS --default_res --channel $channel) ||
		croak "res_finder returned error when called with --default_res"
	RESOLUTION_MIN=$(res_finder $RES_FINDER_EXTRA_ARGS --min_resolution_standard) ||
		croak "res_finder returned error when called with --min_resolution_standard"
	RESOLUTION_MAX=$(res_finder $RES_FINDER_EXTRA_ARGS --max_resolution_standard) ||
		croak "res_finder returned error when called with --max_resolution_standard"
	RESOLUTION_MAXZOOM_NONHIDDEN=$(res_finder $RES_FINDER_EXTRA_ARGS --max_parhand_resolution) ||
		croak "res_finder returned error when called with --max_parhand_resolution"
	RESOLUTION_MAXZOOM=$(res_finder $RES_FINDER_EXTRA_ARGS --max_zoom_max_resolution) ||
		croak "res_finder returned error when called with --max_zoom_max_resolution"
}


check_control_params() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
		croak "check_control_params: wrong number of arguments"
	case $2 in
		start|stop)
			;
		*)
			return 1
			;
	esac
}

daemon_control() {
	check_control_params $* || croak "check_control_params: invalid action '$2'"

	[ -x $1 ] || croak "daemon_control: $1 not executable"
	$1 $2 || croak "$1 failed to $2"
}

service_control() {
	local opts=

	check_control_params $* || {
		case $2 in
			mask|unmask)
				opts=--runtime
				;
			*)
				croak "check_control_params: invalid action '$2'"
				;
		esac
	}
	systemctl $2 $1 $opts || croak "$1 failed to $2"
}

stop_daemons() {
	[ $# -eq 1 ] && [ "$1" ] ||
		croak "stop daemons: wrong number of arguments"

	service_control $TOURD_SERVICE stop
}

start_daemons() {
	[ $# -eq 1 ] && [ "$1" ] ||
		croak "start daemons: wrong number of arguments"

	killall -HUP dptzd || bark "Couldn't update dptzd parameters"
	service_control $TOURD_SERVICE start
}

get_param() {
	[ $# -eq 3 ] && [ "$1" ] && [ "$2" ] && [ "$3" ] ||
		croak "Invalid arguments $*"
	[ -f $3 ] || return 0

	sed -n -e "/^\[$1\]/,/^$/s/^$2[[:blank:]]=[[:blank:]]*//p" $3
}

remove_groups() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] || croak "Invalid arguments $*"
	[ -f $2 ] || return 0

	sed -i -e "/^\[$1.*\]/,/^$/d " $2
}

parhand_readgroupfile() {
	[ $# -eq 1 ] && [ "$1" ] ||
		croak "parhand_readgroupfile: wrong number of arguments"

	$PHC readgroupfile $1 ||
		bark "Could not read parameter file to parhand"
}


write_capturemode_types() {
	local ressets capmodetype i firstcapmode

	ressets=$(bootblocktool -err -x RESOLUTIONSET 2>/dev/null || :)
	if [ "$ressets" ] && [ "$ressets" != ALLSETS ]; then
		firstcapmode=${ressets%%,*}
		capmodetype=$(res_finder $RES_FINDER_EXTRA_ARGS -m $ressets --write_capturemode_type) ||
			croak "res_finder returned error when called with --write_capturemode_type"
		[ ${#ressets} -ne 1 ] || capmodetype="readonly:$capmodetype"
		i=0
		while [ $i -lt 1 ]; do
			safe_print "group ImageSource {
	group I$i {
		group Sensor {
			param CaptureMode {
				parser = Standard2parser
				type = \"$capmodetype\"
				accessControl = \"operator:3;admin:3;capturemoded:1\"
			}
		}
	}
}" /etc/dynamic/param/imagesource_i${i}_sensor_capturemode.conf
			if [ "$firstcapmode" != 1 ]; then
				safe_sed "/ImageSource\.I$i.Sensor/,\$s/^([[:blank:]]*CaptureMode[[:blank:]]*=[[:blank:]]*\"?)1(\"?)$/\1$firstcapmode\2/" 				$CONF_DIR/$CONF_IMAGE_SOURCE ||
					croak "could not save default capture mode"
			fi
			i=$(($i + 1))
		done
	fi
}


### MAIN PROGRAM ###########################################################
err_msg="Wrong number of arguments"

case $# in
	1)
		[ "$1" ] || croak "$err_msg : $*"
		imagesource=0
		;
	2)
		[ "$1" ] && [ "$2" ] || croak "$err_msg : $*"
		imagesource=$2
		;
	*)
		croak "$err_msg : $*"
		;
esac

if [ "$1" = boot ]; then
	RES_FINDER_EXTRA_ARGS=--boot
fi

START_COMMAND=$1

channel=$(($imagesource + 1))

booted_file=/etc/resolution_update/booted
if [ "$1" = boot ] && [ -e $booted_file ]; then
	res_finder $RES_FINDER_EXTRA_ARGS --update_cache
	check_configuration_files
	source_parts boot
	setup_capturemode_sensitive_data
	exit 0
fi

TMP_FILE=$(mktemp /tmp/$SELF.XXXXXX) || croak "Can't create temporary file"

lock

if [ "$1" = boot ]; then
	capturemode=$(bootblocktool -err -x root.ImageSource.I0.Sensor.CaptureMode 2>/dev/null || :)
	if [ "$capturemode" ] && [ "$capturemode" != 1 ]; then
		safe_sed "/ImageSource\.I0.Sensor/,\$s/^([[:blank:]]*CaptureMode[[:blank:]]*=[[:blank:]]*\"?)1(\"?)$/\1$capturemode\2/" 			$CONF_DIR/$CONF_IMAGE_SOURCE || croak "could not save default capture mode"
	fi
	write_capturemode_types
fi

res_finder $RES_FINDER_EXTRA_ARGS --update_cache || bark '"res_finder --update-cache" failed'
[ "$1" = boot ] || init_default_resolutions

case $1 in
	boot)
		check_configuration_files
		source_parts first-boot
		run_parts_deprecated /usr/share/resolution_update/resolution_init.d $START_COMMAND "dummy"
		setup_capturemode_sensitive_data
		if mkdir -p /etc/resolution_update; then
			. /lib/rcscripts/sh/files.sh
			>$booted_file.tmp
			fsynced_write_or_cleanup $booted_file.tmp $booted_file
		fi
		;


	cap_change)
		bark "Live capture mode change support has been deprecated."
		exit 0
		;
	*)
		croak "Invalid argument"
		;
esac