#!/bin/bash

WG_PUBLIC_IP=#Public ip that is routed to current VM
WG_EXPOSED_IP=#Private IP on the host where the public IP is routed to.

INSTANCE_IMAGE=images:debian/13/cloud
LOCAL_TIMEZONE=Europe/paris
WG_DEFAULT_PORT=51820


for i in "$@"; do
  case $i in
    --environment-group-uuid=*)
      ENVIRONMENT_GROUP_UUID="${i#*=}"
      shift
      ;;
    --server-instance-token=*)
      SERVER_INSTANCE_TOKEN="${i#*=}"
      shift
      ;;
    --private-ip=*)
      WG_PRIVATE_IP="${i#*=}"
      shift
      ;;
    --orchestrator-url=*)
      ORCHESTRATOR_URL="${i#*=}"
      shift
      ;;
    --worker-url=*)
      WORKER_URL="${i#*=}"
      shift
      ;;
    --layerops-install-url=*)
      LAYEROPS_INSTALL_URL="${i#*=}"
      shift
      ;;
    --*)
      echo "Unknown option $i" >&2
      exit 1
      ;;
    *)
      ;;
  esac
done

MISSING=""
[ -z "$ENVIRONMENT_GROUP_UUID" ] && MISSING="${MISSING} environment-group-uuid"
[ -z "$SERVER_INSTANCE_TOKEN" ] && MISSING="${MISSING} server-instance-token"
[ -z "$WG_PRIVATE_IP" ] && MISSING="${MISSING} private-ip"
[ -z "$ORCHESTRATOR_URL" ] && MISSING="${MISSING} orchestrator-url"
[ -z "$WORKER_URL" ] && MISSING="${MISSING} worker-url"
[ -z "$LAYEROPS_INSTALL_URL" ] && MISSING="${MISSING} layerops-install-url"
[ ! -z "$MISSING" ] && echo "Missing arguments: $MISSING" >&2 && exit 1

[ -z "$WG_PUBLIC_IP" ] && echo "Missing environment variable: $WG_PUBLIC_IP" >&2 && exit 1
[ -z "$WG_EXPOSED_IP" ] && echo "Missing environment variable: $WG_EXPOSED_IP" >&2 && exit 1

WG_DEVICE_PORT_NAME=udp_wg_expose
INSTANCE_LIST_FILE=/etc/layerops/servers.conf
mkdir -p /etc/layerops/
touch $INSTANCE_LIST_FILE

INSTANCE_NAME=layerops-${ENVIRONMENT_GROUP_UUID:0:8}
INSTANCE_STATUS=$(incus list $INSTANCE_NAME -f compact,noheader 2>&1 | grep $INSTANCE_NAME | awk '{print $2}')
[ $? -ne 0 ] && echo $INSTANCE_STATUS >&2 && exit 1

if [ -z "$INSTANCE_STATUS" ]
then
  USER_DATA=$(cat <<EOF
#cloud-config
bootcmd:
  -
    - cloud-init-per
    - once
    - stop-apt-daily-services
    - systemctl
    - stop
    - apt-daily.service
    - apt-daily-upgrade.service
    - apt-daily.timer
    - apt-daily-upgrade.timer
  -
    - cloud-init-per
    - once
    - apt-daily-timer
    - sh
    - "-c"
    - |
      cat > /lib/systemd/system/apt-daily.timer <<EOF
      [Unit]
      Description=Daily apt download activities

      [Timer]
      OnBootSec=120min
      OnCalendar=*-*-* 6,18:00
      RandomizedDelaySec=12h
      Persistent=true

      [Install]
      WantedBy=timers.target
      EOF
  -
    - cloud-init-per
    - once
    - apt-daily-upgrade-timer
    - sh
    - "-c"
    - |
      cat > /lib/systemd/system/apt-daily-upgrade.timer <<EOF
      [Unit]
      Description=Daily apt upgrade and clean activities
      After=apt-daily.timer

      [Timer]
      OnBootSec=120min
      OnCalendar=*-*-* 6:00
      RandomizedDelaySec=60m
      Persistent=true

      [Install]
      WantedBy=timers.target
      EOF

runcmd:
  - timedatectl set-timezone $LOCAL_TIMEZONE
  - systemctl daemon-reload
  - systemctl restart apt-daily.timer apt-daily-upgrade.timer
  - export WIREGUARD_PRIVATE_IP=$WG_PRIVATE_IP
  - export LAYEROPS_ORCHESTRATOR_URL=$ORCHESTRATOR_URL
  - export LAYEROPS_WORKER_URL=$WORKER_URL
  - export ENVIRONMENT_GROUP_UUID=$ENVIRONMENT_GROUP_UUID
  - export SERVER_INSTANCE_TOKEN=$SERVER_INSTANCE_TOKEN
  - export LOCAL_TIMEZONE="$LOCAL_TIMEZONE"
  - apt uddate
  - apt install -y --no-install-recommends curl
  - curl -s -N -L -o /usr/local/bin/layerops-install $LAYEROPS_INSTALL_URL
  - chmod 755 /usr/local/bin/layerops-install
  - /usr/local/bin/layerops-install init
EOF
)
  err=$(incus launch $INSTANCE_IMAGE $INSTANCE_NAME --config=cloud-init.user-data="$USER_DATA" 2>&1)
  [ $? -ne 0 ] && echo $err >&2 && exit 1
  INSTANCE_STATUS=$(incus list $INSTANCE_NAME -f compact,noheader 2>&1 | awk '{print $2}')
  [ $? -ne 0 ] && echo $INSTANCE_STATUS >&2 && exit 1
fi

if [ "$INSTANCE_STATUS" != "RUNNING" ]
then
  err=$(incus start $INSTANCE_NAME 2>&1)
  [ $? -ne 0 ] && echo $err >&2 && exit 1
fi

WG_EXPOSED_PORT=$(grep $INSTANCE_NAME $INSTANCE_LIST_FILE | awk -F':' '{print $3}')
if [ ${WG_EXPOSED_PORT:-0} -lt $WG_DEFAULT_PORT ]
then
  WG_EXPOSED_PORT=$WG_DEFAULT_PORT
  while grep -q ":$WG_EXPOSED_PORT" $INSTANCE_LIST_FILE; do ((WG_EXPOSED_PORT++)); done;
  echo "$ENVIRONMENT_GROUP_UUID:$INSTANCE_NAME:$WG_EXPOSED_PORT" >> $INSTANCE_LIST_FILE
fi
incus config device list $INSTANCE_NAME | grep -q $WG_DEVICE_PORT_NAME
if [ $? -ne 0 ]
then
  err=$(incus config device add $INSTANCE_NAME $WG_DEVICE_PORT_NAME proxy listen=udp:$WG_EXPOSED_IP:$WG_EXPOSED_PORT connect=udp:127.0.0.1:$WG_DEFAULT_PORT 2>&1)
  [ $? -ne 0 ] && echo $err >&2 && exit 1
fi

echo "{\"wireguardIp\": \"$WG_PUBLIC_IP\", \"wireguardPublicPort\":$WG_EXPOSED_PORT}"
