#!/bin/sh

# Adapted from: https://github.com/balena-os/meta-balena/blob/v2.45.0/meta-balena-common/recipes-containers/balena-supervisor/balena-supervisor/start-balena-supervisor

# We still need to include resin-vars on legacy systems
if [ -f /usr/sbin/resin-vars ]; then
# shellcheck disable=SC1091
  . /usr/sbin/resin-vars
else
# shellcheck disable=SC1091
  . /usr/sbin/balena-config-vars
fi

if ! balena inspect $SUPERVISOR_IMAGE:$SUPERVISOR_TAG > /dev/null; then
    balena load --input /usr/src/supervisor-image.tar
fi

if [ -f /mnt/data/backup.tgz.mounted ]; then
  cp /mnt/data/backup.tgz.mounted /mnt/data/backup.tgz
fi

# Handle apps.json existence
# Keep this before computing SUPERVISOR_CONTAINER_IMAGE_ID
APPSJSON=/mnt/data/apps.json
if [ ! -f "$APPSJSON" ]; then
    if [ -d "$APPSJSON" ]; then
        rm -rf "$APPSJSON"
        balena rm -f balena_supervisor || true
        echo '{}' > "$APPSJSON"
    elif [ ! -e "$APPSJSON" ]; then
        echo '{}' > "$APPSJSON"
    fi
fi

SUPERVISOR_IMAGE_ID=$(balena inspect --format='{{.Id}}' "$SUPERVISOR_IMAGE:$SUPERVISOR_TAG")
SUPERVISOR_CONTAINER_IMAGE_ID=$(balena inspect --format='{{.Image}}' balena_supervisor || echo "")

# If self-signed root CA exists, add the CA for the specified registry
if [ -n "$BALENA_ROOT_CA" ]; then
    BALENA_DECODED_ROOT_CA="$(echo "${BALENA_ROOT_CA}" | base64 -d -w0)"
    NODE_EXTRA_CA_CERTS="/etc/ssl/certs/balenaRootCA.pem"
    CERT_DIR="/mnt/state/root-overlay/etc/docker/certs.d/${REGISTRY_ENDPOINT}"
    CERT_FILE="${CERT_DIR}/ca.crt"
    CERT_CONTENTS=$(if [ -e "$CERT_FILE" ]; then echo $(cat "$CERT_FILE"); fi)

    # Ensure that the contents is correct, install otherwise
    if [ "$BALENA_DECODED_ROOT_CA" != "$CERT_CONTENTS" ]; then
        mkdir -p "$CERT_DIR"
        echo "$BALENA_DECODED_ROOT_CA" > "$CERT_FILE"
    fi
fi

hasValueChanged() {
    KEY="$1"
    NEW_VALUE="$2"
    COLLECTION="$3"
    CURRENT_VALUE=$(echo "$COLLECTION" | jq -r ".$KEY")

    if [ "$CURRENT_VALUE" != "$NEW_VALUE" ];then
        echo "$KEY has changed!"
    else
        return 1
    fi
}

configIsUnchanged() {

    SUPERVISOR_CONTAINER_ENV_JSON="$(balena inspect balena_supervisor | jq '.[0].Config.Env | map(.| { (.[0:index("=")]): .[index("=")+1:] }) | add')"

    if hasValueChanged "BOOT_MOUNTPOINT"       "$BOOT_MOUNTPOINT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "REGISTRY_ENDPOINT"     "$REGISTRY_ENDPOINT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "MIXPANEL_TOKEN"        "$MIXPANEL_TOKEN" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "LED_FILE"              "${LED_FILE}" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "LISTEN_PORT"           "$LISTEN_PORT" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "SUPERVISOR_IMAGE"      "${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "BALENA_ROOT_CA"        "$BALENA_DECODED_ROOT_CA" "$SUPERVISOR_CONTAINER_ENV_JSON" || \
    hasValueChanged "NODE_EXTRA_CA_CERTS"   "$NODE_EXTRA_CA_CERTS" "$SUPERVISOR_CONTAINER_ENV_JSON"; then
        echo "Container config has changed!"
        return 1
    else
        echo "Container config has not changed"
        return 0
    fi
}

runSupervisor() {
    balena rm --force balena_supervisor || true
    balena run --privileged --name balena_supervisor \
        --restart=always \
        --net=host \
        --cidenv=SUPERVISOR_CONTAINER_ID \
        -v /var/run/balena-engine.sock:/var/run/balena-engine.sock \
        -v "$CONFIG_PATH:/boot/config.json"  \
        -v /mnt/data/apps.json:/boot/apps.json \
        -v /resin-data/balena-supervisor:/data \
        -v /proc/net/fib_trie:/mnt/fib_trie \
        -v /var/log/supervisor-log:/var/log \
        -v /:/mnt/root \
        -e DOCKER_ROOT=/mnt/root/var/lib/docker \
        -e DOCKER_SOCKET=/var/run/balena-engine.sock \
        -e "BOOT_MOUNTPOINT=$BOOT_MOUNTPOINT" \
        -e "REGISTRY_ENDPOINT=$REGISTRY_ENDPOINT" \
        -e "MIXPANEL_TOKEN=$MIXPANEL_TOKEN" \
        -e "LED_FILE=${LED_FILE}" \
        -e "LISTEN_PORT=$LISTEN_PORT" \
        -e "SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" \
        -e "BALENA_ROOT_CA=$BALENA_DECODED_ROOT_CA" \
        -e "NODE_EXTRA_CA_CERTS=$NODE_EXTRA_CA_CERTS" \
        "${SUPERVISOR_IMAGE}:${SUPERVISOR_TAG}" \
        node /usr/src/app/dist/app.js --inspect-brk
}

if [ -z "$SUPERVISOR_IMAGE_ID" ]; then
    # No supervisor image exists on the device, try to pull it
    systemctl start update-balena-supervisor
elif [ "$SUPERVISOR_IMAGE_ID" = "$SUPERVISOR_CONTAINER_IMAGE_ID" ] && configIsUnchanged; then
    # Supervisor image exists, and the current supervisor container is created from
    balena start --attach balena_supervisor
else
    # No supervisor container exists or there's a different supervisor image to run
    runSupervisor
fi
