#!/bin/bash

# Parameter Description:
# $1: Configuration file (mandatory parameter)
# $2: Optional parameter that specifies the path to the ipfixprobe library directory.
# If this parameter is not provided, the default value "/usr/lib64/ipfixprobe" will be used.

CONFFILE="/etc/ipfixprobe/$1.conf"

# Help function to display usage instructions
show_help() {
    echo "Usage: $0 CONFIG_NAME [LIBRARY_PATH]"
    echo ""
    echo "CONFIG_NAME: Name of the configuration file (without the '.conf' extension)."
    echo "             The full path will be '/etc/ipfixprobe/[CONFIG_NAME].conf'."
    echo "LIBRARY_PATH: Optional path to the ipfixprobe library directory."
    echo "              If not provided, the default value '/usr/lib64/ipfixprobe' will be used."
    echo ""
    echo "Example 1: Use the default library path:"
    echo "    $0 [name]"
    echo ""
    echo "Example 2: Specify a custom library path:"
    echo "    $0 [name] /usr/local/lib64/ipfixprobe"
    echo ""
}

# Check if the user asked for help
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
    show_help
    exit 0
fi

# Parameter Description:
# $1: Configuration file name (mandatory parameter)
# $2: Optional parameter that specifies the path to the ipfixprobe library directory.
# If this parameter is not provided, the default value "/usr/local


parse_old_format() {
	# Parse the old format of the configuration file
	source "$CONFFILE"
	input=""
	dpdkinput=""
	if [ "$USE_DPDK" = "1" ]; then
		# check
		if [ -z "$DPDK_QUEUES_COUNT" ]; then
			echo "Missing DPDK_QUEUES_COUNT in configuration of DPDK mode."
			exit 1
		fi

		if [ ! -z "$DPDK_LCORES" ]; then
			DPDK_LCORES="--lcores $DPDK_LCORES"
		fi

		if [ -n "$DPDK_OPTS" -a "${DPDK_OPTS:0:1}" != ";" ]; then
			DPDK_OPTS=";$DPDK_OPTS"
		fi

		# create array with input workers affinities
		if [ ! -z "$DPDK_INPUT_WORKER_CPUS" ]; then
			if `declare -p DPDK_INPUT_WORKER_CPUS > /dev/null 2>/dev/null`; then
				if [ "${#DPDK_INPUT_WORKER_CPUS[@]}" -ne "$DPDK_QUEUES_COUNT" ]; then
					echo "DPDK_INPUT_WORKER_CPUS length must be the same as queues count."
					exit 1
				fi
			fi
		fi
		for ((i = 0; i < DPDK_QUEUES_COUNT; i++)); do
			if [ ! -z "$DPDK_INPUT_WORKER_CPUS" ]; then
				affinities[i]="@${DPDK_INPUT_WORKER_CPUS[$i]}"
			else
				affinities[i]=""
			fi
		done

		# set up DPDK interface(s)
		if [ "$DPDK_RING" = "1" ]; then
			# checks
			if [ -z "$DPDK_RING_PATTERN" ]; then
				echo "Missing DPDK_RING_PATTERN in configuration of DPDK_RING mode."
				exit 1
			fi
			if [ -z "$DPDK_RING_STARTIDX" ]; then
				echo "Missing DPDK_RING_STARTIDX in configuration of DPDK_RING mode, using 0."
				DPDK_RING_STARTIDX=0
			fi

			# mring interfaces
			dpdkinput=("-i" "dpdk-ring${affinities[0]};r=$(printf "$DPDK_RING_PATTERN" "$DPDK_RING_STARTIDX")${DPDK_OPTS};e=$DPDK_LCORES $DPDK_EXTRA_EAL")
			plugin_idx=1
			for ((ifc=($DPDK_RING_STARTIDX+1); ifc<($DPDK_RING_STARTIDX + $DPDK_QUEUES_COUNT);ifc++)); do
				dpdkinput+=("-i" "dpdk-ring${affinities[$plugin_idx]};r=$(printf "$DPDK_RING_PATTERN" "$ifc")")
				((plugin_idx++))
			done
		else
			# DPDK port interface
			dpdkinput=("-i" "dpdk${affinities[0]};p=${DPDK_PORT}${DPDK_OPTS};q=$DPDK_QUEUES_COUNT;e=$DPDK_LCORES $DPDK_EXTRA_EAL -a $DPDK_DEVICE")
			for ((ifc=1; ifc<$DPDK_QUEUES_COUNT;ifc++)); do
				dpdkinput+=("-i" "dpdk${affinities[$ifc]}")
			done
		fi
	fi
	if `declare -p INPUT > /dev/null 2>/dev/null`; then
		# list of input plugins
		for ifc in "${!INPUT[@]}"; do
			input="$input -i ${INPUT[ifc]}"
		done
	fi
	CACHE_SIZE_PARAM=""
	if [ ! -z ${CACHE_SIZE+x} ]; then
		CACHE_SIZE_PARAM="size=${CACHE_SIZE}"
	fi
	CACHE_ACTIVET_PARAM=""
	if [ ! -z ${ACTIVE_TIMEOUT+x} ]; then
		CACHE_ACTIVET_PARAM=";active=${ACTIVE_TIMEOUT}"
	fi
	CACHE_INACTIVE_PARAM=""
	if [ ! -z ${INACTIVE_TIMEOUT+x} ]; then
		CACHE_INACTIVE_PARAM=";inactive=${INACTIVE_TIMEOUT}"
	fi
	CACHE_FRAG_ENABLE_PARAM=""
	if [ ! -z ${FRAG_CACHE_ENABLE+x} ]; then
		CACHE_FRAG_ENABLE_PARAM=";frag-enable=${FRAG_CACHE_ENABLE}"
	fi
	CACHE_FRAG_SIZE=""
	if [ ! -z ${FRAG_CACHE_SIZE+x} ]; then
		CACHE_FRAG_SIZE=";frag-size=${FRAG_CACHE_SIZE}"
	fi
	CACHE_FRAG_TIMEOUT=""
	if [ ! -z ${FRAG_CACHE_TIMEOUT+x} ]; then
		CACHE_FRAG_TIMEOUT=";frag-timeout=${FRAG_CACHE_TIMEOUT}"
	fi
	storage="-s cache;${CACHE_SIZE_PARAM}${CACHE_ACTIVET_PARAM}${CACHE_INACTIVE_PARAM}${CACHE_FRAG_ENABLE_PARAM}${CACHE_FRAG_SIZE}${CACHE_FRAG_TIMEOUT}"
	process=""
	if `declare -p PROCESS > /dev/null 2>/dev/null`; then
		# list of input plugins
		for ifc in "${!PROCESS[@]}"; do
			process="$process -p ${PROCESS[ifc]}"
		done
	fi
	UDP_PARAM=""
	if [[ $UDP == "yes" ]]; then
		  UDP_PARAM="udp";
	fi

	NON_BLOCKING_TCP_PARAM=""
	if [[ $NON_BLOCKING_TCP == "yes" ]]; then
		  NON_BLOCKING_TCP_PARAM="non-blocking-tcp";
	fi

	output_affinity=""
	if [ ! -z "$OUTPUT_WORKER_CPU" ]; then
		output_affinity="@$OUTPUT_WORKER_CPU"
	fi

	LZ4_COMPRESSION_PARAM=""
	if [[ $LZ4_COMPRESSION == "yes" ]]; then
		  LZ4_COMPRESSION_PARAM="lz4-compression";
	fi

	output="-o ipfix$output_affinity;host=${HOST:-127.0.0.1};port=${PORT:-4739};id=${LINK:-0};dir=${DIR:-0};${UDP_PARAM};${NON_BLOCKING_TCP_PARAM};${LZ4_COMPRESSION_PARAM};template=${TEMPLATE_REFRESH_RATE:-300}"

	telemetry=""
	if [ "$USE_FUSE" = "1" ]; then
		telemetry="-t ${FUSE_MOUNT_POINT}"
	fi

	exec /usr/bin/ipfixprobe "${dpdkinput[@]}" $input $storage $process $output $telemetry $EXTRA_ARGS
}

if [ -e "$CONFFILE" ]; then
	if grep -q 'INPUT\[' $CONFFILE; then
		echo "WARNING: Legacy configuration format detected. This format is obsolete and will be removed in version 5.2."
		echo "Please transition to the new YAML configuration format. For more details, visit: https://github.com/CESNET/ipfixprobe/blob/master/init/link0.conf.example"
		parse_old_format
	else
		IPFIXPROBE_LIB_DIR="${2:-/usr/lib64/ipfixprobe}"
		command=$(python3 $IPFIXPROBE_LIB_DIR/config2args.py --config $CONFFILE --schema $IPFIXPROBE_LIB_DIR/schema.json)
		status=$?

		if [ $status -ne 0 ]; then
			echo "Cannot convert yaml config" >&2
			echo "$command" >&2
			exit $status
		fi
		eval "exec $command"
	fi
else
	echo "Error: Configuration file '$CONFFILE' does not exist, exitting." >&2
	show_help
	exit 1
fi

exit 0
