###
### config hook
###

dbc_go(){
	local f db happy default_dbtype host newhost port oldhosts authmethod_admin do_config _preconf_list _s _t STATE iformat ifile install_question migrating userdb_prio supported_dbtypes
	. /usr/share/dbconfig-common/dpkg/common
	_dbc_debug "(config) dbc_go() $@"

	dbc_config "$@"

	db_capb backup

	# only do this on install/reconfigure
	if [ "$dbc_command" != "configure" ] && [ "$dbc_command" != "reconfigure" ];
	then
		return 0
	fi

	##
	## register all the dbconfig-common questions
	##
	## note that this can fail in the case that dbconfig-common is being
	## installed at the same time as the dependant package and the latter
	## is preconfigured before we are (no way to avoid this without being
	## in base).  in this case we gracefully exit and defer to the second
	## time the config script is run by dpkg in the postinst.   note if that
	## "hack" in dpkg ever goes away we can still work around the issue so
	## i think it's fair to avoid over-complicating things in the dependency
	## chain.
	##
	if ! dbc_register_debconf; then
		_dbc_debug "dbconfig-common not yet setup, deferring configuration."
		return 0
	fi
	
	# make sure debconf is up to date with on-disk configuration
	dbc_read_package_config
	dbc_preseed_package_debconf

	# Migrate some debconf answers prior to dbc 1.8.50 to the new
	# choices of the templates (can be removed after Debian Stretch)
	if [ "$dbc_dbtype" = "mysql" ] ; then
	    db_get $dbc_package/mysql/method
	    if [ "$RET" = "unix socket" ] ; then
		db_set $dbc_package/mysql/method "Unix socket"
	    elif [ "$RET" = "tcp/ip" ] ; then
		db_set $dbc_package/mysql/method "TCP/IP"
	    fi
	fi
	if [ "$dbc_dbtype" = "pgsql" ] ; then
	    db_get $dbc_package/pgsql/method
	    if [ "$RET" = "unix socket" ] ; then
		db_set $dbc_package/pgsql/method "Unix socket"
	    elif [ "$RET" = "tcp/ip" ] ; then
		db_set $dbc_package/pgsql/method "TCP/IP"
	    elif [ "$RET" = "tcp/ip + ssl" ] ; then
		db_set $dbc_package/pgsql/method "TCP/IP + SSL"
	    fi
	fi

	# Find out whether the database has been purged on a previous occasion. If
	# so, we'll have to give the user a chance to re-install it.
	#
	# We need some check if the package is removed, but not purged.
	# An alternative over using this is to add a new internal template.
	# The drawback of this solution is that preseeding the answer to
	# the purge question is ignored (reset) during package installation
	# so if required this needs to be preseeded when removing the package.
	db_get $dbc_package/purge
	if [ "$RET" = true ]; then
		dbc_command=reconfigure
	fi

	# if we are here due to an error, raising question priorities
	if [ "$dbc_retry_after_error" ] ;then
		dbc_remote_questions_priority="$dbc_prio_high"
		dbc_prio_low="$dbc_prio_high"
		dbc_prio_medium="$dbc_prio_high"
		dbc_prio_high="$dbc_prio_critical"
	fi

    # check out if they're migrating from a non-dbc version
    if [ "$dbc_oldversion" ] && [ "$dbc_first_version" ] && \
        dpkg --compare-versions "$dbc_first_version" gt "$dbc_oldversion"; then
		migrating="yes"
	fi

	# if this is a frontend app, then the user/db type questions get
	# a raised priority
	if [ "$dbc_frontend" ]; then
		userdb_prio="$dbc_prio_medium"
		need_adminpw="false"
	else
		userdb_prio="$dbc_prio_low"
	fi

	# and if they're upgrading from any previous version, we *may*
	# not need to ask for an admin password.  we can't tell at this
	# point because the upgrade files are likely not unpacked at
	# this point, so we will instead ask later in the postinst.
	if [ "$dbc_oldversion" ] && [ "$dbc_command" != "reconfigure" ]; then
		need_adminpw="false"
	fi

	# the first question we ask will differ depending on how we're invoked
	if [ "$migrating" ] || [ "$dbc_retry_after_error" = "upgrade" ] ; then
		install_question="$dbc_package/dbconfig-upgrade"
	elif [ "$dbc_command" = "configure" ]; then
		install_question="$dbc_package/dbconfig-install"
	else
		install_question="$dbc_package/dbconfig-reinstall"
		# if we are reconfiguring (via dpkg-reconfigure), also leave a hint
		# for our future postinst selves so we know we *should* run the code
		# that would otherwise think we were upgrading
		db_set $dbc_package/internal/reconfiguring true
		# Make sure we reset variables that we fset to seen
		dbc_dbpass=""
		# as we are reinstalling, we should know $dbc_dbtype so we can safely
		# call dbc_forget_app_password
		dbc_forget_app_password
	fi

	##
	## start new dbc upgrade section
	##
	# if there is a previously existing version already installed
	# *and* the maintainer has provided the first version that used
	# dbconfig-common *and*  this version is newer than the
	# previously installed version... do the dbc import stuff.
	if [ "$migrating" ]; then
		dbc_migrate
	fi

	# and start our beautiful state-machine
	# we start in STATE=1 (install_question) in all but one situation:
	#   - we're installing a frontend/readonly app
	if [ ! "$dbc_frontend" ]; then
		STATE=1
	else
		STATE=2
	fi
	dbc_statefull=true # Make sure that we can also backup from password questions
	while true; do
	case "$STATE" in
	# state 1 - ask if they want our help at all
	1)
		db_input $dbc_prio_high $install_question || true
	;;
	# state 2 - check to see if they do. 
	#         - see if this is an upgrade newly supporting dbc
	#         - multidb support step 1
	2)
		db_get $install_question
		if [ "$RET" != "true" ]; then
			db_set $dbc_package/internal/skip-preseed true
			return 0;
		fi
		db_set $dbc_package/dbconfig-install true

		##
		## start multidb section
		## 
		# if the dbtype is hardcoded (using config.mysql, etc), use that
		if [ "$dbc_hardcoded_dbtype" ]; then
			dbc_dbtype=$dbc_hardcoded_dbtype
		# else if the package supports multiple dbtypes, help them pick one
		elif [ "$dbc_dbtypes" ]; then
		# loop through the listed dbtypes, fall back to all those available
			supported_dbtypes=$(echo $dbc_dbtypes | sed 's/,/ /g')
			for db in $supported_dbtypes $dbc_all_supported_dbtypes; do
				# if we're already happy, we're already done
				if [ "$happy" ]; then
					true
				# else, if it's supported, installed and unpacked, we're happy
				elif dbc_detect_supported_dbtype $db; then
					# if it's installed, we're happy
					if dbc_detect_installed_dbtype $db; then
						happy="yes"
					fi
					# but in any case it's be the default even if not happy
					default_dbtype=$db	
				fi
				# otherwise, there's no default yet, which is okay
			done

			# now that we're done with that, actually do the debconf stuff

			# if dbc_dbtype isn't already set (from conf file) then
			# use the default as our best guess
			if [ ! "$dbc_dbtype" ]; then
				dbc_dbtype="$default_dbtype"
			fi
			db_set $dbc_package/database-type "$dbc_dbtype"
			db_input $dbc_prio_high $dbc_package/database-type || true
		fi
	;;
	# state 3 - multidb support part 2, pre-seeding, get conn. method
	3)
		if [ "$dbc_dbtypes" ]; then
			db_get $dbc_package/database-type && dbc_dbtype="$RET"
			# now that we have a dbtype, reload common to set other defaults
			dbc_config "$@"
			# Also re-register the templates, as otherwise $dbvendor will
			# not be replaced in the following questions
			dbc_register_debconf
		fi

		# there's a bit more to do with rdbms that support authentication
		if echo "$dbc_authenticated_dbtypes" | grep -q "$dbc_dbtype"; then
			# if these haven't been specified, use defaults
			if [ ! "$dbc_dbadmin" ]; then 
				dbc_dbadmin="$dbc_default_admin"; 
			fi
			if [ ! "$dbc_dbuser" ]; then 
				dbc_dbuser="$dbc_default_dbuser"
			fi
		fi

		if echo "$dbc_fs_dbtypes" | grep -q "$dbc_dbtype"; then
			# if these haven't been specified, use defaults
			if [ ! "$dbc_basepath" ]; then 
				dbc_basepath="$dbc_default_basepath"; 
			fi
		fi

		if [ ! "$dbc_dbname" ]; then 
			dbc_dbname=`echo $dbc_package | tr -d +-.`; 
		fi

		# pre-seed any already defined values into debconf as defaults
		db_set $dbc_package/db/dbname "$dbc_dbname"
		if [ "$dbc_upgrade" ]; then
			db_set $dbc_package/dbconfig-upgrade "$dbc_upgrade"
		fi
		if [ "$dbc_remove" ]; then
			db_set $dbc_package/dbconfig-remove "$dbc_remove"
		fi
		if echo "$dbc_authenticated_dbtypes" | grep -q "$dbc_dbtype"; then
			if [ "$dbc_dbuser" ]; then 
				db_set $dbc_package/db/app-user "$dbc_dbuser"
			fi
			if [ "$dbc_dbpass" ]; then 
				db_set $dbc_package/$dbc_dbtype/app-pass "$dbc_dbpass"
				db_fset $dbc_package/$dbc_dbtype/app-pass seen true
				db_set $dbc_package/app-password-confirm "$dbc_dbpass"
				db_fset $dbc_package/app-password-confirm seen true
			fi
			if [ "$dbc_dbadmin" ]; then
				db_set $dbc_package/$dbc_dbtype/admin-user "$dbc_dbadmin"
			fi
		fi
		if echo "$dbc_remote_dbtypes" | grep -q "$dbc_dbtype"; then
			if [ "$dbc_dbserver" ]; then
				db_set $dbc_package/remote/host "$dbc_dbserver"
			fi
			if [ "$dbc_dbport" ]; then
				db_set $dbc_package/remote/port "$dbc_dbport"
			fi
			if [ "$dbc_ssl" = "true" ] && [ "$dbc_dbtype" = "pgsql" ]; then
				db_set $dbc_package/pgsql/method "TCP/IP + SSL"
			fi
			db_input $dbc_remote_questions_priority $dbc_package/$dbc_dbtype/method || true
		fi
		if echo "$dbc_fs_dbtypes" | grep -q "$dbc_dbtype"; then
			# if these haven't been specified, use defaults
			if [ "$dbc_basepath" ]; then 
				db_set $dbc_package/db/basepath "$dbc_basepath"
			fi
		fi

	;;
	# state 4 - do stuff based on the connection method
	4)
		db_get $dbc_package/$dbc_dbtype/method && dbc_method="$RET"

		if echo "$dbc_remote_dbtypes" | grep -q "$dbc_dbtype"; then
			# if package/method == tcp/ip or tcp/ip + ssl
			if [ "$dbc_method" != "Unix socket" ]; then
				# look at the hosts used in any other dbconfig-using
				# package, and create a list of hosts.
				_preconf_list=` (
				for f in /etc/dbconfig-common/*.conf; do
					test -f $f || continue
					eval \`dbconfig-generate-include --dbserver=_s $f | grep -v '^#'\`
					[ "$_s" ] && echo $_s
				done
				) | sort | uniq`
				# turn the list into a comma separated list if it exists
				# and then substitute it into the list of available hosts
				if [ "$_preconf_list" ]; then
					_preconf_list=`echo $_preconf_list | sed -e 's/ /, /g'`
					_preconf_list="new host, $_preconf_list"
					db_subst $dbc_package/remote/host hosts "$_preconf_list"
					# and then ask them for one
					db_input $dbc_prio_high $dbc_package/remote/host || true
				fi
			# but if it is unix socket, forget all the host stuff
			else
				db_reset $dbc_package/remote/host || true
				db_reset $dbc_package/remote/newhost || true
				db_reset $dbc_package/remote/port || true
			fi
		fi
	;;
	# state 5 - get host / port info if necessary
	5)
		if echo "$dbc_remote_dbtypes" | grep -q "$dbc_dbtype"; then
			if [ "$dbc_method" != "Unix socket" ]; then
				if [ "$_preconf_list" ]; then
					db_get $dbc_package/remote/host 
					host=$RET
				fi

				# if they've chosen "new host" or the host list was empty
				if [ ! "$host" ] || [ "$host" = "new host" ]; then
					# prompt them for a new hostname
					db_input $dbc_prio_high $dbc_package/remote/newhost || true
				fi
			fi
		fi
	;;
	# state 6 - do stuff based on host/port selection
	6)
		if echo "$dbc_remote_dbtypes" | grep -q "$dbc_dbtype"; then
			if [ "$dbc_method" != "Unix socket" ]; then
				if [ ! "$host" ] || [ "$host" = "new host" ]; then
					db_get $dbc_package/remote/newhost 
					newhost="$RET"

					# add the new host to the existing list of hosts
					db_metaget $dbc_package/remote/host choices
					oldhosts="$RET"
					db_subst $dbc_package/remote/host hosts "$oldhosts, $newhost"
					db_set $dbc_package/remote/host "$newhost"
					db_fset $dbc_package/remote/host seen true
				else
					# set the "newhost" to the selected host, because
					# the second time through the configure script we'll
					# need this set
					db_set $dbc_package/remote/newhost "$host"
				fi

				# on what port?
				db_input $dbc_remote_questions_priority $dbc_package/remote/port || true
			fi
		fi
	;;
	# state 7 - pgsql specific auth stuff, part 1
	7)
		if [ "$dbc_dbtype" = "pgsql" ] && [ ! "$dbc_frontend" ]; then
			# postgresql provides multiple auth types, and ssl
			# get the admin auth method
			db_input $dbc_prio_low $dbc_package/pgsql/authmethod-admin || true
		fi
	;;
	# state 8 - pgsql auth stuff, part 2
	8)
		if [ "$dbc_dbtype" = "pgsql" ] && [ ! "$dbc_frontend" ]; then
			db_get $dbc_package/pgsql/authmethod-admin && authmethod_admin="$RET"
			# if we are using ident, we don't need passwords
			if [ "$authmethod_admin" = "ident" ]; then
				need_adminpw="false"
			fi
			# default the user auth method to the admin method
			# ...but only if the answer hasn't already been specified.
			if [ ! "${dbc_authmethod_user}" ]; then
				db_set $dbc_package/pgsql/authmethod-user "$authmethod_admin"
			fi
			db_input $dbc_prio_medium $dbc_package/pgsql/authmethod-user || true
		fi
	;;
	# state 9 - admin/app user/pass, dbname
	9)
		# get the name of the database to use
		db_input $userdb_prio $dbc_package/db/dbname || true

		if echo "$dbc_fs_dbtypes" | grep -q "$dbc_dbtype"; then
			# check the path / permissions to install to
			db_input $dbc_prio_low $dbc_package/db/basepath || true
		fi

		if echo "$dbc_authenticated_dbtypes" | grep -q "$dbc_dbtype"; then

			db_input $userdb_prio $dbc_package/db/app-user || true
			if ! dbc_get_app_pass ; then
			    # Make sure that we can also backup from password questions
			    STATE=$(($STATE - 1))
			    continue
			fi

			# who's the admin user
			if [ ! "$dbc_frontend" ]; then
				db_input $userdb_prio $dbc_package/$dbc_dbtype/admin-user || true
			fi
		fi
		;;
	# state 10 admin password (we need to have the admin-user to fill the
	# template properly
	10)
	    if echo "$dbc_authenticated_dbtypes" | grep -q "$dbc_dbtype"; then
		if [ "$need_adminpw" != "false" ]; then
		    if ! dbc_get_admin_pass ; then
			# Make sure that we can also backup from password questions
			STATE=$(($STATE - 1))
			continue
		    fi
		fi
	    fi
	    ;;
	# * - end state
	*)
		break
	;;
	esac
		if db_go; then
			STATE=$(($STATE + 1))
		else
			STATE=$(($STATE - 1))
		fi

		if [ $STATE -lt 1 ]; then
			if [ "$dbc_config_allow_backup" ]; then
				return 30
			fi
			exit 10
		fi
	done

	dbc_statefull=""
	db_set $dbc_package/internal/skip-preseed true
}

dbc_migrate() {

	# if dbc_load_include is set, determine the format
	# and location of the old config file
	if [ "$dbc_load_include" ]; then
		iformat=`echo $dbc_load_include | cut -d: -f1`
		ifile=`echo $dbc_load_include | cut -d: -f2-`
	fi

	##
	## if they want to import settings from a previous 
	## non-dbc version, do that and mark the questions
	## skipped 
	##
	if [ -z "$ifile" ] || [ ! -f "$ifile" ]; then
		return
	fi

	dbc_logpart "migrating old settings into dbconfig-common: "
	if [ "$dbc_debug" ]; then
		_dbc_debug "dbconfig-load-include $dbc_load_include_args -f $iformat $ifile"
		dbconfig-load-include $dbc_load_include_args -f $iformat $ifile
	fi
	eval `dbconfig-load-include $dbc_load_include_args -f $iformat $ifile`
	if [ "$?" != "0" ]; then
		dbc_logline "failed"
		return
	fi

	# the load script needs to return at least a database type, if it's
	# not a single-dbtype package
	dbc_dbtype=${dbc_dbtype:-${dbc_hardcoded_dbtype:-}}
	if [ -z "$dbc_dbtype" ]; then
		dbc_logline "failed"
		return
	fi

	# if the dbtype is hardcoded, reset it no matter what
	# dbconfig-load-include tells us
	if [ "$dbc_hardcoded_dbtype" ]; then 
		dbc_dbtype="$dbc_hardcoded_dbtype"
	fi
	
	for f in database-type $dbc_dbtype/method db/dbname; do
		db_fset $dbc_package/$f seen true || true
	done
	if echo "$dbc_authenticated_dbtypes" | grep -q "$dbc_dbtype"; then
		for f in pgsql/authmethod-admin pgsql/authmethod-user $dbc_dbtype/admin-user db/app-user; do
			db_fset $dbc_package/$f seen true || true
		done
		db_set $dbc_package/db/app-user "$dbc_dbuser"
		db_set $dbc_package/$dbc_dbtype/app-pass "$dbc_dbpass"
		db_set $dbc_package/app-password-confirm "$dbc_dbpass"
	fi
	if echo "$dbc_remote_dbtypes" | grep -q "$dbc_dbtype"; then
		for f in remote/host remote/newhost remote/port ; do
			db_fset $dbc_package/$f seen true || true
		done
		db_set $dbc_package/remote/host "$dbc_dbserver"
		db_set $dbc_package/remote/newhost "$dbc_dbserver"
		db_set $dbc_package/remote/port "$dbc_dbport"
		if [ "$dbc_dbserver" ]; then
		    if [ "$dbc_ssl" ]; then
			db_set $dbc_package/$dbc_dbtype/method "TCP/IP + SSL"
		    else
			db_set $dbc_package/$dbc_dbtype/method "TCP/IP"
		    fi
		fi
	fi

	db_set $dbc_package/database-type $dbc_dbtype
	db_set $dbc_package/db/dbname "$dbc_dbname"

	dbc_logline "done"
}
