#!/bin/bash

set -e

PRODUCT="docspace"
PACKAGE_SYSNAME="onlyoffice"

APP_DIR="/etc/${PACKAGE_SYSNAME}/${PRODUCT}"
PRODUCT_DIR="/var/www/${PRODUCT}"
LOG_DIR="/var/log/${PACKAGE_SYSNAME}/${PRODUCT}"
OPENRESTY_DIR="/etc/openresty"

APP_HOST="localhost"
APP_PORT="80"

JSON="json -I -f"

[ $(id -u) -ne 0 ] && { echo "Root privileges required"; exit 1; }

while [ "$1" != "" ]; do
	case $1 in
		-ash       | --appshost           ) [ -n "$2" ] && APP_HOST=$2                        && shift ;;
		-asp       | --appsport           ) [ -n "$2" ] && APP_PORT=$2                        && shift ;;
		-ess       | --elasticscheme      ) [ -n "$2" ] && ELK_SCHEME=$2                      && shift ;;
		-esh       | --elastichost        ) [ -n "$2" ] && ELK_HOST=$2                        && shift ;;
		-esp       | --elasticport        ) [ -n "$2" ] && ELK_PORT=$2                        && shift ;;
		-e         | --environment        ) [ -n "$2" ] && ENVIRONMENT=$2                     && shift ;;
		-mysqlh    | --mysqlhost          ) [ -n "$2" ] && DB_HOST=$2                         && shift ;;
		-mysqlport | --mysqlport          ) [ -n "$2" ] && DB_PORT=$2                         && shift ;;
		-mysqld    | --mysqldatabase      ) [ -n "$2" ] && DB_NAME=$2                         && shift ;;
		-mysqlu    | --mysqluser          ) [ -n "$2" ] && DB_USER=$2                         && shift ;;
		-mysqlp    | --mysqlpassword      ) [ -n "$2" ] && DB_PWD=$2                          && shift ;;
		-rdh       | --redishost          ) [ -n "$2" ] && REDIS_HOST=$2                      && shift ;;
		-rdp       | --redisport          ) [ -n "$2" ] && REDIS_PORT=$2                      && shift ;;
		-rdu       | --redisusername      ) [ -n "$2" ] && REDIS_USER=$2                      && shift ;;
		-rdpw      | --redispassword      ) [ -n "$2" ] && REDIS_PASS=$2                      && shift ;;
		-rdb       | --redisdb            ) [ -n "$2" ] && REDIS_DB=$2                        && shift ;;
		-rbpr      | --rabbitmqprotocol   ) [ -n "$2" ] && RABBITMQ_PROTOCOL=$2               && shift ;;
		-rbh       | --rabbitmqhost       ) [ -n "$2" ] && RABBITMQ_HOST=$2                   && shift ;;
		-rbu       | --rabbitmquser       ) [ -n "$2" ] && RABBITMQ_USER=$2                   && shift ;;
		-rbpw      | --rabbitmqpassword   ) [ -n "$2" ] && RABBITMQ_PASSWORD=$2               && shift ;;
		-rbp       | --rabbitmqport       ) [ -n "$2" ] && RABBITMQ_PORT=$2                   && shift ;;
		-mk        | --machinekey         ) [ -n "$2" ] && CORE_MACHINEKEY=$2                 && shift && echo "$CORE_MACHINEKEY" > "$APP_DIR/.private/machinekey" ;;
		-js        | --jwtsecret          ) [ -n "$2" ] && DOCUMENT_SERVER_JWT_SECRET=$2      && shift ;;
		-jh        | --jwtheader          ) [ -n "$2" ] && DOCUMENT_SERVER_JWT_HEADER=$2      && shift ;;
		-du        | --dashboardsusername ) [ -n "$2" ] && DASHBOARDS_USERNAME=$2             && shift ;;
		-dp        | --dashboardspassword ) [ -n "$2" ] && DASHBOARDS_PASSWORD=$2             && shift && echo "$DASHBOARDS_PASSWORD" > "$APP_DIR/.private/dashboards-password" ;;
		-docsurl   | --docsurl            ) [ -n "$2" ] && DOCUMENT_SERVER_URL_EXTERNAL=$2    && shift ;;
		-h   | -?  | --help )
			echo 
			echo "GENERAL OPTIONS:"
			echo "  --appshost            <ip>                ${PRODUCT} host/IP"
			echo "  --appsport            <port>              ${PRODUCT} port (default: 80)"
			echo "  --environment         <name>              Environment name (community/developer/enterprise)"
			echo "  --machinekey          <key>               Setting for core.machinekey"

			echo
			echo "DOCUMENT SERVER OPTIONS:"
			echo "  --docsurl             <URL>               ${PACKAGE_SYSNAME} docs server URL (e.g., http://docs.example.com:8083)"
			echo "  --jwtheader           <header>            HTTP header for JWT (default: AuthorizationJwt)"
			echo "  --jwtsecret           <secret>            JWT secret key"

			echo 
			echo "DATABASE OPTIONS (MySQL):"
			echo "  --mysqlhost           <host>              MySQL server host (default: localhost)"
			echo "  --mysqlport           <port>              MySQL port (default: 3306)"
			echo "  --mysqldatabase       <db_name>           ${PRODUCT} database name"
			echo "  --mysqluser           <username>          ${PRODUCT} database user"
			echo "  --mysqlpassword       <password>          ${PRODUCT} database password"

			echo 
			echo "CACHE OPTIONS (Redis):"
			echo "  --redishost           <host>              Redis host (default: localhost)"
			echo "  --redisport           <port>              Redis port (default: 6379)"
			echo "  --redisusername       <username>          Redis username (default: none)"
			echo "  --redispassword       <password>          Redis password (default: none)"
			echo "  --redisdb             <index>             Redis database index (default: 0)"

			echo 
			echo "QUEUE OPTIONS (RabbitMQ):"
			echo "  --rabbitmqprotocol    <protocol>          RabbitMQ protocol (default: amqp)"
			echo "  --rabbitmqhost        <host>              RabbitMQ host (default: localhost)"
			echo "  --rabbitmqport        <port>              RabbitMQ port (default: 5672)"
			echo "  --rabbitmquser        <username>          RabbitMQ user"
			echo "  --rabbitmqpassword    <password>          RabbitMQ password"

			echo 
			echo "SEARCH OPTIONS (OpenSearch):"
			echo "  --elasticscheme       <http|https>        Protocol for search (default: http)"
			echo "  --elastichost         <host>              OpenSearch host (default: localhost)"
			echo "  --elasticport         <port>              OpenSearch port (default: 9200)"

			echo 
			echo "DASHBOARDS OPTIONS:"
			echo "  --dashboardsusername  <username>          Username for OpenSearch Dashboards"
			echo "  --dashboardspassword  <password>          Password for OpenSearch Dashboards"

			echo 
			echo "HELP:"
			echo "  -h, -?, --help                            Show this help message"
			echo
			exit 0
		;;

		* )
			echo "Unknown parameter $1" 1>&2
			exit 1
		;;
	esac
	shift
done

install_json() {
	if ! command -v json >/dev/null 2>&1; then
		echo -n "Install json package... "
		if curl -fsSL "https://github.com/trentm/json/raw/master/lib/json.js" -o /usr/bin/json && [ -s /usr/bin/json ]; then
			chmod 755 /usr/bin/json
			command -v json >/dev/null 2>&1 && echo "OK" || { echo "ERROR: install failed"; return 1; }
		else
			echo "ERROR: download failed"; rm -f /usr/bin/json; return 1
		fi
	fi
}

json_configuration() {
	local JSON_FILE="$1" FIELD_PATH="$2" FIELD_VALUE="$3"
	${JSON} "$JSON_FILE" -e \
	"var p='$FIELD_PATH'.split('.'),k=p.pop(),o=p.reduce((a,x)=>(a[x]??={}),this);
	o[k] = $( [[ $FIELD_VALUE =~ ^(\{.*\}|\[.*\])$ ]] && printf %s "$FIELD_VALUE" || printf "'%s'" "$FIELD_VALUE")" >/dev/null 2>&1
}

env_configuration() {
	local FILE=$1 KEY=$2 VALUE=$3
	if grep -q "^${KEY}=" "$FILE"; then
		sed -i "s|^${KEY}=.*|${KEY}=$(printf '%q' "$VALUE")|" "$FILE"
	else
		printf '%s=%s\n' "$KEY" "$VALUE" >> "$FILE"
	fi
}

restart_services() {
	chown -R ${PACKAGE_SYSNAME}:${PACKAGE_SYSNAME} $APP_DIR $PRODUCT_DIR $LOG_DIR /var/www/$PACKAGE_SYSNAME/Data
	systemctl restart openresty

	echo -n "Updating database... "
	systemctl start "${PRODUCT}-migration-runner" || true
	timeout 60 bash -c "while systemctl is-active "${PRODUCT}-migration-runner" &>/dev/null; do sleep 1; done" && echo "OK" || echo "Timeout reached"

	echo -n "Restarting services... "
	systemctl enable "${SERVICES_LIST[@]}" >/dev/null 2>&1
	systemctl restart "${SERVICES_LIST[@]}"
	echo "OK"
}

input_db_params(){
	CONNECTION_STRING=$(json -f "${USER_CONF}" ConnectionStrings.default.connectionString 2>/dev/null)
	if [[ -n "$CONNECTION_STRING" ]]; then
		DB_HOST=${DB_HOST:-$(grep -oP 'Server=\K[^;]*'   <<<"$CONNECTION_STRING" || :)}
		DB_PORT=${DB_PORT:-$(grep -oP 'Port=\K[^;]*'     <<<"$CONNECTION_STRING" || :)}
		DB_NAME=${DB_NAME:-$(grep -oP 'Database=\K[^;]*' <<<"$CONNECTION_STRING" || :)}
		DB_USER=${DB_USER:-$(grep -oP 'User ID=\K[^;]*'  <<<"$CONNECTION_STRING" || :)}
		DB_PWD=${DB_PWD:-$(grep -oP 'Password=\K[^;]*'  <<<"$CONNECTION_STRING" || :)}
	fi

	if [[ -t 0 ]]; then
		[[ -n "$DB_HOST" ]] || read -e -i "${DB_HOST:-localhost}"          -p "Database host: " DB_HOST
		[[ -n "$DB_PORT" ]] || read -e -i "${DB_PORT:-3306}"               -p "Database port: " DB_PORT
		[[ -n "$DB_NAME" ]] || read -e -i "${DB_NAME:-${PACKAGE_SYSNAME}}" -p "Database name: " DB_NAME
		[[ -n "$DB_USER" ]] || read -e -i "${DB_USER:-root}"               -p "Database user: " DB_USER
		[[ -n "$DB_PWD"  ]] || read -e -i "${DB_PWD}"                      -p "Database password: " DB_PWD
	else
		: "${DB_HOST:=localhost}" "${DB_PORT:=3306}" "${DB_NAME:=${PACKAGE_SYSNAME}}" "${DB_USER:=root}" "${DB_PWD:=}"
	fi

	CONNECTION_STRING="Server=$DB_HOST;Port=$DB_PORT;Database=$DB_NAME;User ID=$DB_USER;Password=$DB_PWD;Pooling=true; \
Character Set=utf8; AutoEnlist=false; SSL Mode=none;AllowPublicKeyRetrieval=true;Connection Timeout=30;Maximum Pool Size=300"
}

establish_mysql_conn(){
	echo -n "Trying to establish MySQL connection... "
	command -v mysql >/dev/null 2>&1 || { echo "MySQL client not found"; exit 1; }

	MYSQL="mysql -P${DB_PORT} -h${DB_HOST} -u${DB_USER}"
	[ -n "${DB_PWD}" ] && MYSQL="${MYSQL} -p${DB_PWD}"

	if ! $MYSQL -e ";" >/dev/null 2>&1; then
		systemctl start "${MYSQL_PACKAGE}"
		$MYSQL -e ";" >/dev/null 2>&1 || {
			echo "FAILURE: MySQL connection error"
			echo "Please check \`$0 --help\` for MySQL connection parameters and run:"
			echo "  $0 [PARAMETERS]"
			exit 1
		}
	fi

	if $PACKAGE_MANAGER mysql-server >/dev/null 2>&1 || $PACKAGE_MANAGER mysql-community-server >/dev/null 2>&1; then
		change_mysql_config
	fi

	json_configuration "${USER_CONF}" "ConnectionStrings.default.connectionString" "${CONNECTION_STRING}"
	json_configuration "${APP_DIR}/apisystem.${ENVIRONMENT}.json" "ConnectionStrings.default.connectionString" "${CONNECTION_STRING}"
	json_configuration "${USER_CONF}" "migration.enabled" "true"

	env_configuration "$APP_DIR/systemd.env" JDBC_URL "${DB_HOST}:${DB_PORT}"
	env_configuration "$APP_DIR/systemd.env" JDBC_DATABASE "$DB_NAME"
	env_configuration "$APP_DIR/systemd.env" JDBC_USER_NAME "$DB_USER"
	env_configuration "$APP_DIR/systemd.env" JDBC_PASSWORD "$DB_PWD"

	sed "s&\(\"ConnectionString\":\).*&\1 \"$(printf "%q" "${CONNECTION_STRING}")\"&" -i $PRODUCT_DIR/services/ASC.Migration.Runner/appsettings.runner.json

	echo "OK"
}

change_mysql_config(){
	if [ "$DIST" = "RedHat" ]; then
		CNF_PATH="/etc/my.cnf"
		CNF_SERVICE_PATH="/usr/lib/systemd/system/mysqld.service"
		grep -q "\[mysqld\]" "$CNF_PATH" || CNF_PATH="/etc/my.cnf.d/server.cnf"
		grep -q "\[mysqld\]" "$CNF_PATH" || exit 1

		grep -q "\[Unit\]" "$CNF_SERVICE_PATH" || CNF_SERVICE_PATH="/lib/systemd/system/mysqld.service"
		grep -q "\[Unit\]" "$CNF_SERVICE_PATH" || CNF_SERVICE_PATH="/lib/systemd/system/mariadb.service"
		grep -q "\[Unit\]" "$CNF_SERVICE_PATH" || exit 1
	elif [ "$DIST" = "Debian" ]; then
		sed -i "s/#max_connections.*/max_connections = 1000/" /etc/mysql/my.cnf || true
		CNF_PATH="/etc/mysql/mysql.conf.d/mysqld.cnf"
		CNF_SERVICE_PATH="/lib/systemd/system/mysql.service"
	fi

	sed -i "/^\[mysqld\]/!b;/bind-address/ s|.*|bind-address = 127.0.0.1|; t; a bind-address = 127.0.0.1" "${CNF_PATH}"
	sed -i "/^\[mysqld\]/!b;/mysqlx_bind_address/ s|.*|mysqlx_bind_address = 127.0.0.1|; t; a mysqlx_bind_address = 127.0.0.1" "${CNF_PATH}"
	sed -i '/skip-networking/d' "$CNF_PATH" || true
	sed -i '/^default-authentication-plugin/d' "$CNF_PATH" || true

	grep -q "^sql_mode" "$CNF_PATH" \
		&& sed -i -E "s|^(sql_mode).*|\1 = 'NO_ENGINE_SUBSTITUTION'|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a sql_mode = 'NO_ENGINE_SUBSTITUTION'" "$CNF_PATH"

	grep -q "^max_connections" "$CNF_PATH" \
		&& sed -i -E "s|^(max_connections).*|\1 = 1000|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a max_connections = 1000" "$CNF_PATH"

	grep -q "^group_concat_max_len" "$CNF_PATH" \
		&& sed -i -E "s|^(group_concat_max_len).*|\1 = 2048|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a group_concat_max_len = 2048" "$CNF_PATH"

	grep -q "^max_allowed_packet" "$CNF_PATH" \
		&& sed -i -E "s|^(max_allowed_packet).*|\1 = 1048576000|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a max_allowed_packet = 1048576000" "$CNF_PATH"

	grep -q "^character_set_server" "$CNF_PATH" \
		&& sed -i -E "s|^(character_set_server).*|\1 = utf8|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a character_set_server = utf8" "$CNF_PATH"

	grep -q "^collation_server" "$CNF_PATH" \
		&& sed -i -E "s|^(collation_server).*|\1 = utf8_general_ci|" "$CNF_PATH" \
		|| sed -i "/\[mysqld\]/a collation_server = utf8_general_ci" "$CNF_PATH"

	if [ -e "$CNF_SERVICE_PATH" ]; then
		grep -q "^LimitNOFILE" "$CNF_SERVICE_PATH" \
			&& sed -i -E "s|^(LimitNOFILE).*|\1 = infinity|" "$CNF_SERVICE_PATH" \
			|| sed -i "/\[Service\]/a LimitNOFILE = infinity" "$CNF_SERVICE_PATH"

		grep -q "^LimitMEMLOCK" "$CNF_SERVICE_PATH" \
			&& sed -i -E "s|^(LimitMEMLOCK).*|\1 = infinity|" "$CNF_SERVICE_PATH" \
			|| sed -i "/\[Service\]/a LimitMEMLOCK = infinity" "$CNF_SERVICE_PATH"
	fi

	systemctl daemon-reload 
	systemctl enable ${MYSQL_PACKAGE} >/dev/null 2>&1
	systemctl restart ${MYSQL_PACKAGE}
}

setup_openresty(){
	echo -n "Configuring openresty... "
	OPENRESTY_CONF="/usr/local/openresty/nginx/conf/nginx.conf"
	PROXY_CONF="${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}-proxy.conf"

	cp -rf "${APP_DIR}/openresty/nginx.conf.template" "${OPENRESTY_CONF}"
	[ ! -f "${PROXY_CONF}" ] && cp -rf "${PROXY_CONF}.template" "${PROXY_CONF}"
	[ -f "${PROXY_CONF}.save" ] && { cp -rf "${PROXY_CONF}.save" "${PROXY_CONF}" && rm -f "${PROXY_CONF}.save"; }
	[ ! -f "${OPENRESTY_DIR}/mime.types" ] && cp -rf "$(dirname "${OPENRESTY_CONF}")/mime.types" "${OPENRESTY_DIR}"

	DOMAIN="$(json -f "${USER_CONF}" files.docservice.url.portal | awk -F[/:] '{print ($1=="https")?$4:""}')"
	CERTIFICATE_PATH="$(grep -oP 'ssl_certificate\s+\K\S+' "${PROXY_CONF}" | tr -d ';')"
	CERTIFICATE_KEY_PATH="$(grep -oP 'ssl_certificate_key\s+\K\S+' "${PROXY_CONF}" | tr -d ';')"
	# (DS v3.0.0) Fix the problem related to environment change
	[[ -f "${APP_DIR}/appsettings.production.json" ]] && DOMAIN="${DOMAIN:-$(json -f "${APP_DIR}/appsettings.production.json" files.docservice.url.portal | awk -F[/:] '{print ($1=="https")?$4:""}')}"
	if [ -n "${DOMAIN}" ] && [ -n "${CERTIFICATE_PATH}" ] && [ -n "${CERTIFICATE_KEY_PATH}" ]; then
		echo -n "Configuring SSL... "
		"/usr/bin/${PRODUCT}-ssl-setup" -f "${DOMAIN}" "${CERTIFICATE_PATH}" "${CERTIFICATE_KEY_PATH}" > /dev/null 2>&1
	else
		cp -rf "${PROXY_CONF}.template" "${PROXY_CONF}"
		sed -i "s/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1${APP_PORT}\3\4/" "${PROXY_CONF}"
	fi

	sed -i "s!\(^worker_processes\).*;!\1 ${NGINX_WORKER_PROCESSES:-$(grep -c '^processor' /proc/cpuinfo)};!" "${OPENRESTY_CONF}"
	sed -i "s!\(worker_connections\).*;!\1 ${NGINX_WORKER_CONNECTIONS:-$(ulimit -n)};!" "${OPENRESTY_CONF}"

	if [ "$DIST" = "RedHat" ]; then
		# Remove default nginx settings [error] port 80 is already in use
		if [ -f /etc/nginx/nginx.conf ]; then
			if grep -q "server {"  /etc/nginx/nginx.conf ; then
				sed -e '$a}' -e '/server {/,$d' -i /etc/nginx/nginx.conf
				systemctl reload nginx
			fi
		fi
		
		shopt -s nocasematch
		if command -v getenforce >/dev/null 2>&1; then
			case "$(getenforce)" in
				enforcing|permissive)
					PORTS=(5000 5001 5003 5004 5005 5006 5007 5009 5010 5011 5012 5013 5014 5015 5027 5032 5033 5034 5075 5099 5100 5124 5157 5158 8080 9090 9834 9899)
					setsebool -P httpd_can_network_connect on
					EXISTING_PORTS="$(semanage port -l | awk '$1=="http_port_t" && $2=="tcp"{for(i=3;i<=NF;i++)print $i}' | tr ',' '\n' | tr -d ' ')"
					for PORT in "${PORTS[@]}"; do
						grep -qx "$PORT" <<< "${EXISTING_PORTS}" || \
						semanage port -a -t http_port_t -p tcp "$PORT" >/dev/null 2>&1 || \
						semanage port -m -t http_port_t -p tcp "$PORT" >/dev/null 2>&1 || true
					done
				;;
				disabled) : ;;
			esac
		fi

		if $PACKAGE_MANAGER firewalld >/dev/null 2>&1; then
			if [ "$(systemctl is-active firewalld.service)" = "active" ]; then
				firewall-cmd --permanent --zone=public --add-service=http
				firewall-cmd --permanent --zone=public --add-service=https
				systemctl restart firewalld.service
			fi
		fi
	elif [ "$DIST" = "Debian" ]; then
		if ! id "nginx" >/dev/null 2>&1; then
			rm -rf /var/log/nginx/* /var/cache/nginx/*
			useradd -s /bin/false nginx
		fi
	fi

	NGINX_USER="nginx" NGINX_GROUP="nginx"
	NGINX_LOG_DIR=/var/log/nginx/

	getent group "${NGINX_GROUP}" >/dev/null || groupadd "${NGINX_GROUP}"
	id "${NGINX_USER}" >/dev/null 2>&1 || useradd -g "${NGINX_GROUP}" -s "${OPENRESTY_DIR}/" "${NGINX_USER}"
	chown -R "${NGINX_USER}:${NGINX_GROUP}" "${OPENRESTY_DIR}"*
	[ -d "${NGINX_LOG_DIR}" ] || { mkdir -p "${NGINX_LOG_DIR}" && chown "${NGINX_USER}:${NGINX_GROUP}" "${NGINX_LOG_DIR}"; }

	systemctl enable openresty >/dev/null 2>&1
	echo "OK"
}

# Function gets Document server host and port using regular expression, we need it to check connection
parse_external_docs_url () {
	if [[ $DOCUMENT_SERVER_URL_EXTERNAL =~ ^(https?://)?([^:/]+)(:([0-9]+))?(/.*)?$ ]]; then 
		DOCUMENT_SERVER_PORT="${BASH_REMATCH[4]:-80}"
		DOCUMENT_SERVER_HOST="${BASH_REMATCH[2]}"

		[[ -n ${BASH_REMATCH[1]} ]] || DOCUMENT_SERVER_URL_EXTERNAL="http://$DOCUMENT_SERVER_HOST:$DOCUMENT_SERVER_PORT"
	fi
}

setup_docs() {
	echo -n "Configuring docs... "

	if [ $1 == "LOCAL_DOCS_SERVER" ]; then
		DS_CONF_DIR="/etc/${PACKAGE_SYSNAME}/documentserver"
		DOCUMENT_SERVER_PORT=$(grep -oP '(?<=:)\d+(?=\s)' ${DS_CONF_DIR}/nginx/ds.conf)
		sed 's/\(listen .*:\)\([0-9]\{2,5\}\b\)\( default_server\)\?\(;\)/\1'${DOCUMENT_SERVER_PORT}'\3\4/' -i ${DS_CONF_DIR}/nginx/ds.conf 
		: "${DOCUMENT_SERVER_JWT_SECRET:=$(json -f ${DS_CONF_DIR}/local.json services.CoAuthoring.secret.inbox.string 2>/dev/null)}"
		: "${DOCUMENT_SERVER_JWT_HEADER:=$(json -f ${DS_CONF_DIR}/local.json services.CoAuthoring.token.inbox.header 2>/dev/null)}"

		json_configuration "${DS_CONF_DIR}/local.json" "rabbitmq" "{ url: '${RABBITMQ_URI}' }"
		json_configuration "${DS_CONF_DIR}/local.json" "services.CoAuthoring.redis" "{ host: '${REDIS_HOST}', port: '${REDIS_PORT}' }"
		json_configuration "${DS_CONF_DIR}/local.json" "services.CoAuthoring.redis.options" "{
			${REDIS_USER:+username: '${REDIS_USER}',}
			${REDIS_PASS:+password: '${REDIS_PASS}',}
			${REDIS_DB:+database: '${REDIS_DB}',}
		}"
		
		chown ds:ds ${DS_CONF_DIR}/local.json
		usermod -aG ${PACKAGE_SYSNAME} ds
		chmod g+rwxs /var/www/${PACKAGE_SYSNAME}/Data
		systemctl restart ds-converter ds-docservice ds-metrics
	elif [ $1 == "EXTERNAL_DOCS_SERVER" ]; then
		APP_HOST=$(curl -s -4 ifconfig.me)
		: "${DOCUMENT_SERVER_JWT_SECRET:=$(json -f "${USER_CONF}" services.CoAuthoring.secret.inbox.string 2>/dev/null)}"
		: "${DOCUMENT_SERVER_JWT_HEADER:=$(json -f "${USER_CONF}" services.CoAuthoring.token.inbox.header 2>/dev/null)}"
	fi

	sed "0,/proxy_pass .*;/{s#proxy_pass .*;#proxy_pass ${DOCUMENT_SERVER_URL_EXTERNAL:-http://$APP_HOST:$DOCUMENT_SERVER_PORT};#}" -i ${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}.conf
	json_configuration "${USER_CONF}" "files.docservice.secret.value" "${DOCUMENT_SERVER_JWT_SECRET}" 
	json_configuration "${USER_CONF}" "files.docservice.secret.header" "${DOCUMENT_SERVER_JWT_HEADER:-"AuthorizationJwt"}" 
	json_configuration "${USER_CONF}" "files.docservice.url.public" "${DOCUMENT_SERVER_URL_EXTERNAL:-"/ds-vpath/"}"
	json_configuration "${USER_CONF}" "files.docservice.url.internal" "${DOCUMENT_SERVER_URL_EXTERNAL:-"http://${APP_HOST}:${DOCUMENT_SERVER_PORT}"}"
	json_configuration "${USER_CONF}" "files.docservice.url.portal" "http://${APP_HOST}:${APP_PORT}"
	
	echo "OK"
}

change_elasticsearch_config(){
	systemctl stop opensearch
	if $PACKAGE_MANAGER elasticsearch >/dev/null 2>&1; then
		systemctl disable elasticsearch >/dev/null 2>&1
		systemctl stop elasticsearch >/dev/null 2>&1
	fi

	ELASTIC_SEARCH_CONF_PATH="/etc/opensearch/opensearch.yml"
	ELASTIC_SEARCH_JAVA_CONF_PATH="/etc/opensearch/jvm.options"

	sed -i '/^plugins\.security\./,/^[^ ]/d' /etc/opensearch/opensearch.yml
	/usr/share/opensearch/bin/opensearch-plugin list | grep -qx "opensearch-security" && \
		/usr/share/opensearch/bin/opensearch-plugin remove opensearch-security >/dev/null 2>&1

	if [[ ! -f "$APP_DIR/.private/opensearch-version" || $(cat "$APP_DIR/.private/opensearch-version") != *"${ELASTIC_VERSION}"* ]]; then
		/usr/share/opensearch/bin/opensearch-plugin list | grep -q "ingest-attachment" && \
			/usr/share/opensearch/bin/opensearch-plugin remove -s ingest-attachment
		/usr/share/opensearch/bin/opensearch-plugin install -s -b ingest-attachment
	fi

	[ -f "${ELASTIC_SEARCH_CONF_PATH}.rpmnew" ] && cp -f "${ELASTIC_SEARCH_CONF_PATH}.rpmnew" "${ELASTIC_SEARCH_CONF_PATH}"
	[ -f "${ELASTIC_SEARCH_JAVA_CONF_PATH}.rpmnew" ] && cp -f "${ELASTIC_SEARCH_JAVA_CONF_PATH}.rpmnew" "${ELASTIC_SEARCH_JAVA_CONF_PATH}"

	grep -q "^indices.fielddata.cache.size" "$ELASTIC_SEARCH_CONF_PATH" \
	&& sed -i -E "s|^(indices\.fielddata\.cache\.size).*|\1: 30%|" "$ELASTIC_SEARCH_CONF_PATH" \
	|| echo "indices.fielddata.cache.size: 30%" >> "$ELASTIC_SEARCH_CONF_PATH"

	grep -q "^indices.memory.index_buffer_size" "$ELASTIC_SEARCH_CONF_PATH" \
	&& sed -i -E "s|^(indices\.memory\.index_buffer_size).*|\1: 30%|" "$ELASTIC_SEARCH_CONF_PATH" \
	|| echo "indices.memory.index_buffer_size: 30%" >> "$ELASTIC_SEARCH_CONF_PATH"

	grep -q "Dlog4j2.formatMsgNoLookups" "$ELASTIC_SEARCH_JAVA_CONF_PATH" \
	&& sed -i -E "s|(Dlog4j2\.formatMsgNoLookups).*|\1=true|" "$ELASTIC_SEARCH_JAVA_CONF_PATH" \
	|| echo "-Dlog4j2.formatMsgNoLookups=true" >> "$ELASTIC_SEARCH_JAVA_CONF_PATH"

	sed -i '/-XX:+HeapDumpOnOutOfMemoryError/d' "$ELASTIC_SEARCH_JAVA_CONF_PATH"

	local SAFE_MEMORY=$(( ( $(free --mega | grep -oP '\d+' | head -n 1) - 1024 ) / 2 )) # half of the remaining memory after the 1 GB reserve for the OS
	local HEAP=$(( SAFE_MEMORY < 2048 ? 1 : SAFE_MEMORY < 4096 ? 2 : 4 ))g #if <2GB -> 1GB; <4GB -> 2GB; otherwise -> 4GB
	grep -qE "^[^#]*-Xms[0-9]g" "${ELASTIC_SEARCH_JAVA_CONF_PATH}" && sed -i "s/-Xms[0-9]g/-Xms${HEAP}/" "${ELASTIC_SEARCH_JAVA_CONF_PATH}" || echo "-Xms${HEAP}" >> "${ELASTIC_SEARCH_JAVA_CONF_PATH}"
	grep -qE "^[^#]*-Xmx[0-9]g" "${ELASTIC_SEARCH_JAVA_CONF_PATH}" && sed -i "s/-Xmx[0-9]g/-Xmx${HEAP}/" "${ELASTIC_SEARCH_JAVA_CONF_PATH}" || echo "-Xmx${HEAP}" >> "${ELASTIC_SEARCH_JAVA_CONF_PATH}"

	[ -d /etc/opensearch/ ] && chmod g+ws /etc/opensearch/
}

setup_elasticsearch() {
	echo -n "Configuring opensearch... "

	: "${ELK_SCHEME:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Scheme 2>/dev/null)}"
	: "${ELK_HOST:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Host 2>/dev/null)}"
	: "${ELK_PORT:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Port 2>/dev/null)}"
	: "${ELK_THREADS:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Threads 2>/dev/null)}"
	: "${ELK_SCHEME:="http"}" "${ELK_HOST:="localhost"}" "${ELK_PORT:="9200"}" "${ELK_THREADS:="1"}"

	json_configuration "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Scheme" "${ELK_SCHEME}"
	json_configuration "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Host" "${ELK_HOST-"localhost"}"
	json_configuration "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Port" "${ELK_PORT-"9200"}"
	json_configuration "${APP_DIR}/elastic.${ENVIRONMENT}.json" "elastic.Threads" "1"

	if [ $1 == "LOCAL_ELASTIC_SERVER" ]; then
		change_elasticsearch_config
		systemctl enable opensearch >/dev/null 2>&1
		systemctl restart opensearch
	fi
	echo "OK"
}

setup_dashboards() {
	echo -n "Configuring dashboards... "

	DASHBOARDS_CONF_PATH="/etc/opensearch-dashboards/opensearch_dashboards.yml"
	: "${DASHBOARDS_PASSWORD:=$(generate_key "dashboards-password" 20)}"

	# configure login&pass for Dashboards, used by Nginx HTTP Basic Authentication
	echo "${DASHBOARDS_USERNAME:-"onlyoffice"}:$(openssl passwd -6 -stdin <<< "${DASHBOARDS_PASSWORD}")" > /etc/openresty/.htpasswd_dashboards
	chown ${NGINX_USER}:${NGINX_GROUP} /etc/openresty/.htpasswd_dashboards && chmod 640 /etc/openresty/.htpasswd_dashboards

	# enable connection with opensearch
	: "${ELK_SCHEME:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Scheme 2>/dev/null)}"
	: "${ELK_HOST:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Host 2>/dev/null)}"
	: "${ELK_PORT:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Port 2>/dev/null)}"
	sed -i "s~\(opensearch\.hosts:\).*~\1 \[${ELK_SCHEME}://${ELK_HOST}:${ELK_PORT}\]~" ${DASHBOARDS_CONF_PATH}
	sed -i '/^opensearch\_security/d' ${DASHBOARDS_CONF_PATH}
	if /usr/share/opensearch-dashboards/bin/opensearch-dashboards-plugin list --allow-root | grep "securityDashboards*" > /dev/null 2>&1 ; then
		/usr/share/opensearch-dashboards/bin/opensearch-dashboards-plugin remove securityDashboards --allow-root > /dev/null 2>&1
	fi

	# set basePath variable to get access to Dashboards from a remote host
	sed 's_.*\(server.basePath:\).*_\1 "/dashboards"_' -i ${DASHBOARDS_CONF_PATH}
	sed 's_.*\(server.rewriteBasePath:\).*_\1 "true"_' -i ${DASHBOARDS_CONF_PATH}

	systemctl enable opensearch-dashboards >/dev/null 2>&1
	systemctl restart opensearch-dashboards
	echo "OK"
}

setup_fluentbit() {
	echo -n "Configuring fluent-bit... "

	: "${ELK_SCHEME:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Scheme 2>/dev/null)}"
	: "${ELK_HOST:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Host 2>/dev/null)}"
	: "${ELK_PORT:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Port 2>/dev/null)}"
	: "${ELK_SCHEME:="http"}" "${ELK_HOST:="localhost"}" "${ELK_PORT:="9200"}" "${OPENSEARCH_INDEX:="${PACKAGE_SYSNAME}-fluent-bit"}"

	sed -i "s/OPENSEARCH_HOST/$ELK_HOST/g; s/OPENSEARCH_PORT/$ELK_PORT/g; s/OPENSEARCH_INDEX/$OPENSEARCH_INDEX/g; s/OPENSEARCH_SCHEME/$ELK_SCHEME/g" ${APP_DIR}/fluent-bit.conf
	cp -f ${APP_DIR}/fluent-bit.conf /etc/fluent-bit/fluent-bit.conf

	systemctl enable fluent-bit >/dev/null 2>&1
	systemctl restart fluent-bit
	echo "OK"
}

setup_redis() {
	echo -n "Configuring redis... "
	: "${REDIS_HOST:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.0.Host 2>/dev/null)}"
	: "${REDIS_PORT:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.0.Port 2>/dev/null)}"
	: "${REDIS_USER:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.UserName 2>/dev/null)}"
	: "${REDIS_PASS:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.Password 2>/dev/null)}"
	: "${REDIS_DB:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.Database 2>/dev/null)}"
	: "${REDIS_HOST:=127.0.0.1}" "${REDIS_PORT:=6379}" "${REDIS_DB:=0}"

	json_configuration "${APP_DIR}/redis.${ENVIRONMENT}.json" "Redis.Hosts" "[{ Host: \"${REDIS_HOST}\", Port: \"${REDIS_PORT}\" }]"
	[[ -n "${REDIS_USER}" ]] && json_configuration "${APP_DIR}/redis.${ENVIRONMENT}.json" "Redis.UserName" "${REDIS_USER}"
	[[ -n "${REDIS_PASS}" ]] && json_configuration "${APP_DIR}/redis.${ENVIRONMENT}.json" "Redis.Password" "${REDIS_PASS}"
	[[ -n "${REDIS_DB}" ]] && json_configuration "${APP_DIR}/redis.${ENVIRONMENT}.json" "Redis.Database" "${REDIS_DB}"

	env_configuration "$APP_DIR/systemd.env" REDIS_HOST "${REDIS_HOST}"
	env_configuration "$APP_DIR/systemd.env" REDIS_PORT "${REDIS_PORT}"
	env_configuration "$APP_DIR/systemd.env" REDIS_DB "${REDIS_DB}"
	[[ -n "${REDIS_USER}" ]] && env_configuration "$APP_DIR/systemd.env" REDIS_USERNAME "${REDIS_USER}"
	[[ -n "${REDIS_PASS}" ]] && env_configuration "$APP_DIR/systemd.env" REDIS_PASSWORD "${REDIS_PASS}"

	sed -i -e "s~\(redis_host =\).*~\1 \"$REDIS_HOST\"~" -e "s~\(redis_port =\).*~\1 $REDIS_PORT~" \
		-e "s~\(redis_user =\).*~\1 \"$REDIS_USER\"~" -e "s~\(redis_pass =\).*~\1 \"$REDIS_PASS\"~" \
		-e "s~\(redis_db =\).*~\1 $REDIS_DB~" "${OPENRESTY_DIR}/conf.d/${PACKAGE_SYSNAME}.conf"

	if [ $1 == "LOCAL_REDIS_SERVER" ]; then
		REDIS_CONF=$(find /etc/redis/redis.conf /etc/redis.conf /etc/valkey/valkey.conf -type f 2>/dev/null | head -n 1)

		sed "s_\(^bind\).*_\1 ${REDIS_HOST}_" -i ${REDIS_CONF}
		sed -r "/^save\s[0-9]+/d" -i ${REDIS_CONF}

		systemctl enable $REDIS_PACKAGE >/dev/null 2>&1
		systemctl restart $REDIS_PACKAGE
	fi

	echo "OK"
}

setup_rabbitmq() {
	echo -n "Configuring rabbitmq... "

	: "${RABBITMQ_HOST:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Hostname 2>/dev/null)}"
	: "${RABBITMQ_PORT:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Port 2>/dev/null)}"
	: "${RABBITMQ_USER:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.UserName 2>/dev/null)}"
	: "${RABBITMQ_PASSWORD:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Password 2>/dev/null)}"
	: "${RABBITMQ_URI:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Uri 2>/dev/null)}"
	: "${RABBITMQ_PROTOCOL:=${RABBITMQ_URI%%://*}}"
	: "${RABBITMQ_PROTOCOL:=amqp}" "${RABBITMQ_HOST:=localhost}" "${RABBITMQ_PORT:=5672}" "${RABBITMQ_USER:=guest}" "${RABBITMQ_PASSWORD:=guest}"
	: "${RABBITMQ_URI:=${RABBITMQ_PROTOCOL}://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@${RABBITMQ_HOST}:${RABBITMQ_PORT}/}"

	json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Hostname" "${RABBITMQ_HOST}"
	json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.UserName" "${RABBITMQ_USER}"
	json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Password" "${RABBITMQ_PASSWORD}"
	json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Port" "${RABBITMQ_PORT}"
	json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.VirtualHost" "/"
	[[ ${RABBITMQ_PROTOCOL} != "amqps" ]] || json_configuration "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" "RabbitMQ.Uri" "${RABBITMQ_URI}"
	env_configuration "$APP_DIR/systemd.env" RABBIT_URI "${RABBITMQ_URI}"

	if [ $1 == "LOCAL_RABBITMQ_SERVER" ]; then
		systemctl enable rabbitmq-server >/dev/null 2>&1
		systemctl restart rabbitmq-server
	fi

	echo "OK"
}

generate_key() {
	local FILE_NAME=$1
	local KEY_LENGTH=${2:-12}
	local KEY=${3:-$( [[ -f ${APP_DIR}/.private/$FILE_NAME ]] && cat ${APP_DIR}/.private/$FILE_NAME || tr -dc A-Za-z0-9 </dev/urandom | head -c $KEY_LENGTH )}
	echo "${KEY}" | tee "${APP_DIR}/.private/$FILE_NAME"
	chmod -R 600 ${APP_DIR}/.private
}

product_configuration(){
	echo -n "Configuring ${PRODUCT}... "

	${PACKAGE_MANAGER} ${PACKAGE_SYSNAME}-documentserver-ee >/dev/null 2>&1 && : "${ENVIRONMENT:="enterprise"}" ||
	${PACKAGE_MANAGER} ${PACKAGE_SYSNAME}-documentserver-de >/dev/null 2>&1 && : "${ENVIRONMENT:="developer"}" ||
	: "${ENVIRONMENT:="community"}"

	USER_CONF="$APP_DIR/appsettings.$ENVIRONMENT.json"

	#Creating environment configuration files 
	environmentFiles=("appsettings.$ENVIRONMENT.json" "apisystem.$ENVIRONMENT.json" "elastic.$ENVIRONMENT.json" "rabbitmq.$ENVIRONMENT.json" "redis.$ENVIRONMENT.json")

	for FILE in "${environmentFiles[@]}"; do
		if [ ! -e "$APP_DIR/${FILE}" ]; then
			cp -f "$APP_DIR/${FILE}.template" "$APP_DIR/${FILE}" 2>/dev/null || echo "{}" > "$APP_DIR/${FILE}"
			chmod o-rwx "$APP_DIR/${FILE}"
		fi
	done

	[ -f "$APP_DIR/systemd.env" ] || touch "$APP_DIR/systemd.env"
	chmod o-rwx "$APP_DIR/systemd.env"

	env_configuration "$APP_DIR/systemd.env" ENVIRONMENT "${ENVIRONMENT}"
	env_configuration "$APP_DIR/systemd.env" SPRING_PROFILES_ACTIVE "prod,server"
	env_configuration "$APP_DIR/systemd.env" DOCSPACE_INTERNAL "true"
	env_configuration "$APP_DIR/systemd.env" DOCSPACE_TRANSPORT "http"
	env_configuration "$APP_DIR/systemd.env" DOCSPACE_HOST "0.0.0.0"
	env_configuration "$APP_DIR/systemd.env" DOCSPACE_PORT "5158"

	: "${CORE_MACHINEKEY:=$(generate_key "machinekey")}"
	json_configuration "${USER_CONF}" "core.machinekey" "${CORE_MACHINEKEY}"
	json_configuration "${APP_DIR}/apisystem.${ENVIRONMENT}.json" "core.machinekey" "${CORE_MACHINEKEY}"

	json_configuration "${USER_CONF}" "core.base-domain" "${APP_HOST}"
	json_configuration "${APP_DIR}/apisystem.${ENVIRONMENT}.json" "core.base-domain" "${APP_HOST}"

	env_configuration "$APP_DIR/systemd.env" SPRING_APPLICATION_SIGNATURE_SECRET "${CORE_MACHINEKEY}"
	env_configuration "$APP_DIR/systemd.env" SPRING_APPLICATION_ENCRYPTION_SECRET "${ENCRYPTION_SECRET:-$(generate_key "encryption")}"

	echo "OK"
}

# Function below checks if there is a connection to the external service. 0 - OK, connection established
check_connection_external_services() {
	exec {FD}<> /dev/tcp/$1/$2 && exec {FD}>&-
	HOST_RESPONSE=$?

	if [[ $HOST_RESPONSE -ne 0 ]]; then
		echo -e "$3 external server is not responding: $1:$2"
		return $HOST_RESPONSE
	fi

	return $HOST_RESPONSE
}

stop_services() {
	echo -n "Stopping services... "
	systemctl stop "${SERVICES_LIST[@]}" 'ds-*.service' 2>&1
	echo "OK"
}

SERVICES=(login api socket studio-notify notify \
people-server files files-services studio backup api-system \
clear-events backup-background ssoauth doceditor healthchecks \
identity-authorization identity-api sdk management telegram ai ai-service mcp)
SERVICES_LIST=("${SERVICES[@]/#/${PRODUCT}-}")

if command -v yum >/dev/null 2>&1; then
	DIST="RedHat"
	PACKAGE_MANAGER="rpm -q"
	MYSQL_PACKAGE="mysqld"
	REDIS_PACKAGE="redis"
	SYSTEMD_DIR="/usr/lib/systemd/system"
	${PACKAGE_MANAGER} valkey &>/dev/null && REDIS_PACKAGE="valkey" || true
elif command -v apt >/dev/null 2>&1; then
	DIST="Debian"
	PACKAGE_MANAGER="dpkg -s"
	MYSQL_PACKAGE="mysql"
	REDIS_PACKAGE="redis-server"
	SYSTEMD_DIR="$(dirname $(dpkg-query -L ${PRODUCT}-api | grep systemd/system/))"
fi

stop_services
install_json
product_configuration

if $PACKAGE_MANAGER mysql-client >/dev/null 2>&1 || $PACKAGE_MANAGER mysql-community-client >/dev/null 2>&1; then
	input_db_params
	establish_mysql_conn || exit $?
fi

# Identifying whether dependencies are local or external
: "${REDIS_HOST:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.0.Host 2>/dev/null)}"
: "${RABBITMQ_HOST:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Hostname 2>/dev/null)}"
: "${ELK_HOST:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Host 2>/dev/null)}"
: "${DOCUMENT_SERVER_URL_EXTERNAL:-$(URL=$(json -f "${USER_CONF}" files.docservice.url.public 2>/dev/null); curl -fsS "${URL}" >/dev/null 2>&1 && echo "${URL}" || echo "")}"
[[ -n "$RABBITMQ_HOST" && "$RABBITMQ_HOST" != localhost && "$RABBITMQ_HOST" != 127.0.0.1 ]] && EXTERNAL_RABBITMQ_FLAG=true || { RABBITMQ_HOST=""; unset EXTERNAL_RABBITMQ_FLAG; }
[[ -n "$REDIS_HOST" && "$REDIS_HOST" != localhost && "$REDIS_HOST" != 127.0.0.1 ]] && EXTERNAL_REDIS_FLAG=true || { REDIS_HOST=""; unset EXTERNAL_REDIS_FLAG; }
[[ -n "$ELK_HOST" && "$ELK_HOST" != localhost && "$ELK_HOST" != 127.0.0.1 ]] && EXTERNAL_ELK_FLAG=true || { ELK_HOST=""; unset EXTERNAL_ELK_FLAG; }
[[ -n $DOCUMENT_SERVER_URL_EXTERNAL && "$DOCUMENT_SERVER_URL_EXTERNAL" != *"localhost"* && "$DOCUMENT_SERVER_URL_EXTERNAL" != *"127.0.0.1"* ]] || DOCUMENT_SERVER_URL_EXTERNAL=""

if [[ $EXTERNAL_REDIS_FLAG ]]; then
	: "${REDIS_PORT:=$(json -f "${APP_DIR}/redis.${ENVIRONMENT}.json" Redis.Hosts.0.Port 2>/dev/null)}"
	check_connection_external_services "$REDIS_HOST" "$REDIS_PORT" "Redis"
	setup_redis "EXTERNAL_REDIS_SERVER"
elif $PACKAGE_MANAGER $REDIS_PACKAGE >/dev/null 2>&1; then
	setup_redis "LOCAL_REDIS_SERVER"
fi

if [[ $EXTERNAL_RABBITMQ_FLAG ]]; then
	: "${RABBITMQ_PORT:=$(json -f "${APP_DIR}/rabbitmq.${ENVIRONMENT}.json" RabbitMQ.Port 2>/dev/null)}"
	check_connection_external_services "$RABBITMQ_HOST" "$RABBITMQ_PORT" "RabbitMQ"
	setup_rabbitmq "EXTERNAL_RABBITMQ_SERVER"
elif $PACKAGE_MANAGER rabbitmq-server >/dev/null 2>&1; then
	setup_rabbitmq "LOCAL_RABBITMQ_SERVER"
fi

if [[ $EXTERNAL_ELK_FLAG ]]; then
	: "${ELK_PORT:=$(json -f "${APP_DIR}/elastic.${ENVIRONMENT}.json" elastic.Port 2>/dev/null)}"
	check_connection_external_services "$ELK_HOST" "$ELK_PORT" "Elasticsearch"
	setup_elasticsearch "EXTERNAL_ELASTIC_SERVER"
elif $PACKAGE_MANAGER opensearch >/dev/null 2>&1; then
	ELASTIC_VERSION=$(awk '/build:/{f=1} f&&/version:/{gsub(/"/,"",$2);print $2; exit}' /usr/share/opensearch/manifest.yml 2>/dev/null || echo "2.18.0")
	setup_elasticsearch "LOCAL_ELASTIC_SERVER"
fi

if [[ $DOCUMENT_SERVER_URL_EXTERNAL ]]; then
	parse_external_docs_url "$DOCUMENT_SERVER_URL_EXTERNAL"
	check_connection_external_services "$DOCUMENT_SERVER_HOST" "$DOCUMENT_SERVER_PORT" "${PACKAGE_SYSNAME^^} Docs"
	setup_docs "EXTERNAL_DOCS_SERVER"
elif $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-de >/dev/null 2>&1 || $PACKAGE_MANAGER ${PACKAGE_SYSNAME}-documentserver-ee >/dev/null 2>&1; then
	setup_docs "LOCAL_DOCS_SERVER"
else
	echo "WARNING: ${PACKAGE_SYSNAME^^} Docs is not installed."
	${JSON} "${USER_CONF}" -e 'delete this.files.docservice'
fi

if $PACKAGE_MANAGER opensearch-dashboards >/dev/null 2>&1; then
	setup_dashboards
fi

if $PACKAGE_MANAGER fluent-bit >/dev/null 2>&1; then
	setup_fluentbit
fi

if $PACKAGE_MANAGER openresty >/dev/null 2>&1; then
	setup_openresty
fi

restart_services

# Truncate MySQL DB to make opensearch work with updated app. Strictly after restart_services ()
if $PACKAGE_MANAGER opensearch >/dev/null 2>&1; then
	[[ ! -f "$APP_DIR/.private/opensearch-version" || $(cat "$APP_DIR/.private/opensearch-version") != *"${ELASTIC_VERSION}"* ]] && $MYSQL "$DB_NAME" -e "TRUNCATE webstudio_index";
	echo "$ELASTIC_VERSION" > $APP_DIR/.private/opensearch-version
	chmod -R 600 $APP_DIR/.private
fi
