#!/bin/sh -e

os="$(cat "${__global}/explorer/os")"
case "${os}" in
	devuan|debian)
	;;
	*)
		echo "Your OS '${os}' is currently not supported." > /dev/stderr
		exit 1
	;;
esac

current_conferences="$(cat "${__object}/explorer/jitsi-status" | grep -E "^jitsi_conferences[[:space:]]" | cut -d ' ' -f 2)"

JICOFO_AUTHPASSWORD="$(cat "${__object}/explorer/jicofo-authpassword")"
if [ -z "${JICOFO_AUTHPASSWORD}" ]; then
	# This is probably a first time installation, we'll generate the
	# password which will be set in debconf by this type
	# https://github.com/jitsi/jicofo/blob/aafb61b5363a1c4abdbf08e1444a6276b807993e/debian/postinst#L43
	JICOFO_AUTHPASSWORD="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c 16)"
fi

ABORT_CONFERENCE_COUNT="$(cat "${__object}/parameter/abort-conference-count")"

if [ -n "${current_conferences}" ] && [ -n "${ABORT_CONFERENCE_COUNT}" ] && \
	[ "${ABORT_CONFERENCE_COUNT}" -le "${current_conferences}" ]; then
	cat <<-EOF
Early bail out was requested when at least ${ABORT_CONFERENCE_COUNT} conferences are taking place.
There are currently ${current_conferences} active conferences.

Try again at a later time or remove or increase --abort-conference-count
	EOF
	exit 1
fi

JITSI_HOST="${__target_host}"
if [ -f "${__object}/parameter/jitsi-version" ]; then
	# This has been deprecated and will be removed 'soon'
	JITSI_VERSION="$(cat "${__object}/parameter/jitsi-version")"
else
	# Note this won't be a parameter anymore, we won't let users stay behind
	JITSI_VERSION="$(cat "${__type}/files/jitsi-version")"
fi
TURN_SERVER="$(cat "${__object}/parameter/turn-server")"
TURN_SECRET="$(cat "${__object}/parameter/turn-secret")"

if [ -z "${TURN_SERVER}" ]; then
	TURN_SERVER="${JITSI_HOST}"
fi

# The rest is loosely based on Jitsi's documentation
# https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart

# Setup repositories
## First the signing keys
### Remove old signing key
__apt_key "jitsi_meet_2016" \
	--keyid "66A9 CD05 95D6 AFA2 4729  0D3B EF8B 479E 2DC1 389C" \
	--use-deprecated-apt-key \
	--state "absent"
### Add new signing key
require="__apt_key/jitsi_meet_2016" __apt_key jitsi_meet_2021 \
	--source "${__type}/files/apt_2021.gpg" \
	--state "present"
## Now the repositories (they are a tad weird, so distribution is 'stable/')
require="__apt_key/jitsi_meet_2021" __apt_source jitsi_meet \
	--uri 'https://download.jitsi.org' \
	--distribution 'stable/' \
	--state present
## Ensure apt cache is up-to-date
require="__apt_source/jitsi_meet" __apt_update_index

export require="${require} __apt_source/jitsi_meet __apt_update_index"

# Pre-feed debconf settings, so Jitsi's installation has a good config
# shellcheck source=type/__jitsi_meet/files/debconf_settings.sh
. "${__type}/files/debconf_settings.sh"  # This defines DEBCONF_SETTINGS
__debconf_set_selections jitsi_meet --line "${DEBCONF_SETTINGS}"
export require="${require} __debconf_set_selections/jitsi_meet"

# Install and upgrade packages as needed
#   NOTE: we are doing version pinning again, but it breaks sometimes when
#         the version is not the latest.
#         This happens because dependencies might not be properly resolved.
#         To avoid this, this type must be maintained up to date.
#         If we don't use this, keeping Jitsi's up to date is very difficult.
__package_apt jitsi-meet --version "${JITSI_VERSION}"

# Proceed only after installation/upgrade has finished
export require="__package_apt/jitsi-meet"

# TODO: generalise and move out
# Prep nginx for acme settings

NGINX_ETC="/etc/nginx"

#
# Setup the acme-challenge snippet
#
__directory "${NGINX_ETC}/snippets" --state present
require="__directory${NGINX_ETC}/snippets" __file "${NGINX_ETC}/snippets/acme-challenge.conf" \
  --mode 644 \
  --source - << EOF
# This file is managed remotely, all changes will be lost

# This was heavily inspired by debops.org.

# Automatic Certificate Management Environment (ACME) support.
# https://tools.ietf.org/html/draft-ietf-acme-acme-01
# https://en.wikipedia.org/wiki/Automated_Certificate_Management_Environment


# Return the ACME challenge present in the server public root.
# If not found, switch to global web server root.
location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        try_files \$uri @well-known-acme-challenge;
}

# Return the ACME challenge present in the global server public root.
# If not present, redirect request to a specified domain.
location @well-known-acme-challenge {
        root /usr/share/jitsi-meet;
        default_type "text/plain";
        try_files \$uri @redirect-acme-challenge;
}

# Redirect the ACME challenge to a different host. If a redirect loop is
# detected, return 404.
location @redirect-acme-challenge {
        if (\$arg_redirect) {
                return 404;
        }
        return 307 \$scheme://${ACME_DOMAIN}\$request_uri?redirect=yes;
}

# Return 404 if ACME challenge well known path is accessed directly.
location = /.well-known/acme-challenge/ {
    return 404;
}
EOF

__directory "${NGINX_ETC}/sites-available" --state present
require="__directory${NGINX_ETC}/sites-available" __file "${NGINX_ETC}/sites-available/default" \
  --mode 644 \
  --source - << EOF
# This file is managed remotely, all changes will be lost

server_names_hash_bucket_size 64;

types {
# nginx's default mime.types doesn't include a mapping for wasm or wav.
    application/wasm     wasm;
    audio/wav            wav;
}

server {

        # Listen on IPv4
        listen 80;
        # Note: there is an ipv6only=off flag, but it is Linux-only
        #       incidentally, that defaults to "on", which is what causes
        #       not having the double listen to listen on IPv6-only
        listen [::]:80;

        server_name welcome;

        root /srv/www/sites/welcome/public;

        include snippets/acme-challenge.conf;

        location / {
                return 301 https://\$host\$request_uri;
        }
}
EOF

# Starting from 2.0.7210, jitsi defines following nginx upstreams
__directory "${NGINX_ETC}/conf.d" --state present
require="__directory${NGINX_ETC}/conf.d" __file "${NGINX_ETC}/conf.d/prosody.conf" \
  --mode 644 \
  --source - << EOF
upstream prosody {
    zone upstreams 64K;
    server 127.0.0.1:5280;
    keepalive 2;
}
EOF
require="__directory${NGINX_ETC}/conf.d" __file "${NGINX_ETC}/conf.d/jvb1.conf" \
  --mode 644 \
  --source - << EOF
upstream jvb1 {
    zone upstreams 64K;
    server 127.0.0.1:9090;
    keepalive 2;
}
EOF

if [ -f "${__object}/parameter/secured-domains" ]; then
  SECURED_DOMAINS_STATE='present'
else
  SECURED_DOMAINS_STATE='absent'
fi

# This is the main host config
PROSODY_MAIN_CONFIG="YES"
# Prosody settings for common components (jvb, focus, ...)
# shellcheck source=type/__jitsi_meet/files/prosody.cfg.lua.sh
. "${__type}/files/prosody.cfg.lua.sh"  # This defines PROSODY_CONFIG
__file "/etc/prosody/conf.d/00_jitsi_base.cfg.lua" \
	--group prosody \
	--mode 0440 \
	--source - <<EOF
${PROSODY_CONFIG}
EOF

# Clean up zauth.cfg.lua file, which we don't use now
__file "/etc/prosody/conf.d/${JITSI_HOST}.zauth.cfg.lua" \
  --state absent

export SECURED_DOMAINS_STATE
export JITSI_HOST
export JICOFO_AUTHPASSWORD
"${__type}/files/jicofo.conf.sh" | \
	__file /etc/jitsi/jicofo/jicofo.conf --mode 0444 --source '-'

# Enable the private colibri REST API end point for better stats
__file "/etc/jitsi/videobridge/jvb.conf" --mode 0444 --source '-' <<EOFJVB
videobridge {
    http-servers {
        public {
            port = 9090
        }
        private {
            port = 8080
        }
    }
    websockets {
        enabled = true
        domain = "${JITSI_HOST}:443"
        tls = true
    }
    apis {
        rest {
            enabled = true
        }
    }
}
EOFJVB

# Enable simple per-domain body customisation
__file "/usr/share/jitsi-meet/body.html" \
	--mode 0644 \
	--source '-' <<EOF
<!--#include virtual="body-\${host}.html" -->
EOF

# These two should be changed on new release
EXPORTER_VERSION="1.2.1"
EXPORTER_CHECKSUM="sha256:46d4b8475b72fd7632a5203f1cc3c7067bed4629902b7780a1da85e4e06c2129"
EXPORTER_URL="https://github.com/systemli/prometheus-jitsi-meet-exporter/releases/download/${EXPORTER_VERSION}/prometheus-jitsi-meet-exporter_${EXPORTER_VERSION}_linux_amd64.tar.gz"
if [ -f "${__object}/parameter/disable-prometheus-exporter" ]; then
	EXPORTER_STATE="absent"
else
	EXPORTER_STATE="present"
fi
__evilham_single_binary_service prometheus-jitsi-meet-exporter \
	--state "${EXPORTER_STATE}" \
	--do-not-manage-user \
	--user "nobody" \
	--group "nogroup" \
	--version "${EXPORTER_VERSION}" \
	--checksum "${EXPORTER_CHECKSUM}" \
	--url "${EXPORTER_URL}" \
	--unpack \
	--service-args "-videobridge-url 'http://localhost:8080/colibri/stats' -web.listen-address ':9888'"

#
# Setup interpreter assets if requested
# See: https://gitlab.com/mfmt/jsi/
#
jsi_updated_on="2022-04-21"
__link "/usr/share/jitsi-meet/interpreters.html" \
	--type symbolic \
	--source "/opt/jsi/static/index.html.sample"
__directory /opt/jsi --mode 0755
export require="__directory/opt/jsi"
__download /opt/jsi/jsi.tar.gz \
	--url 'https://gitlab.com/mfmt/jsi/-/archive/1d2cceaf615ee61c0bba80e5bddc61c5d1018303/jsi-1d2cceaf615ee61c0bba80e5bddc61c5d1018303.tar.gz' \
	--sum "sha256:b020141093daa9937507b098f358d0be994834c3e23866a457fc5140415a0c53"
export require="__download/opt/jsi/jsi.tar.gz"
__unpack /opt/jsi/jsi.tar.gz \
	--preserve-archive \
	--tar-strip 1 \
	--destination /opt/jsi/static \
	--onchange "$(cat <<EOF
# Patch style.css to be served on /i/
sed -i.tmp -E \
	-e 's!url[(]/img/welcome-background.png[)]!url(/i/img/welcome-background.png)!' \
	/opt/jsi/static/style.css
# Patch jsi.js to be served on /i/
#   and so it always uses the domain it's served from
#   and so it uses /i/ROOM for the form
sed -i.tmp -E \
	-e 's!substr[(][0-9]+[)]!substr(3)!' \
	-e 's!config[.]jitsimeet_url!url.host!' \
	-e 's!(window[.]location[.]href)[[:space:]]*=[[:space:]]*"/"!\1 = "/i/"!' \
	/opt/jsi/static/jsi.js
# Patch the sample index.html, so it loads external_api.js from same host
#   and to easen up on the branding
#   and to enable browser cache
sed -i.tmp -E \
	-e "s!src=[^>]*(/external_api.js).!src='\1'!" \
	-e "s!<h1>[^<]*</h1>!<h1>Jitsi Meetings with interpreter</h1>!" \
	-e "s!https://meet.mayfirst.org!/!" \
	-e "s!(style.css|jsi.js)([^?])!\1?v=${jsi_updated_on:?}\2!" \
	/opt/jsi/static/index.html.sample
EOF
)"
