#!/bin/sh

set -e
. /usr/share/debconf/confmodule

maskcidr() {
   local x=${1##*255.}
   set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
   x=${1%%$3*}
   echo $(( $2 + (${#x}/4) ))
}

db_input_not_empty() {
  priority=${1}
  question=${2}

  while :; do
    db_input ${priority} ${question} || true
    db_go
    db_get ${question}
    if [ -n "${RET}" ]; then
      break
    fi

    # Make sure we ask the user for input
    priority="critical"
    db_input critical lxd/bridge-empty-error || true
  done
}

random_ipv4() {
  while :; do
    SUBNET="10.$(shuf -i 1-255 -n 1).$(shuf -i 0-255 -n 1)"

    # Check if well known
    if [ "${SUBNET}" = "10.10.10" ]; then
      continue
    fi

    # Check if used locally
    if ip -4 route show | grep -q ${SUBNET}; then
      continue
    fi

    # Attempt to see if used behind the gateway
    if ping -n -q ${SUBNET}.1 -c 1 -W 1 >/dev/null 2>&1; then
      continue
    fi

    if ping -n -q ${SUBNET}.254 -c 1 -W 1 >/dev/null 2>&1; then
      continue
    fi

    break
  done

  echo ${SUBNET}
}

random_ipv6() {
  while :; do
    SUBNET="fd$(printf "%x" $(shuf -i 0-255 -n 1)):$(printf "%x" $(shuf -i 0-65535 -n 1)):$(printf "%x" $(shuf -i 0-65535 -n 1)):$(printf "%x" $(shuf -i 0-65535 -n 1))"

    # Check if used locally
    if ip -6 route show | grep -q ${SUBNET}; then
      continue
    fi

    # Attempt to see if used behind the gateway
    if ping6 -n -q ${SUBNET}::1 -c 1 -W 1 >/dev/null 2>&1; then
      continue
    fi

    break
  done

  echo ${SUBNET}
}

# Attempt to read existing configuration into debconf
if [ -e /etc/default/lxd-bridge ]; then
    . /etc/default/lxd-bridge

    db_set lxd/setup-bridge ${USE_LXD_BRIDGE:-false}
    db_set lxd/update-profile ${UPDATE_PROFILE:-true}
    db_set lxd/bridge-name ${LXD_BRIDGE}

    if [ -n "${LXD_IPV4_ADDR}" ]; then
        db_set lxd/bridge-ipv4 true
    else
        db_set lxd/bridge-ipv4 false
    fi

    db_set lxd/bridge-ipv4-address ${LXD_IPV4_ADDR}

    CIDR=$(maskcidr ${LXD_IPV4_NETMASK})
    if [ "${CIDR}" = "0" ]; then
        db_set lxd/bridge-ipv4-netmask ""
    else
        db_set lxd/bridge-ipv4-netmask ${CIDR}
    fi

    db_set lxd/bridge-ipv4-dhcp-first $(echo ${LXD_IPV4_DHCP_RANGE} | cut -d, -f1)
    db_set lxd/bridge-ipv4-dhcp-last $(echo ${LXD_IPV4_DHCP_RANGE} | cut -d, -f2)
    db_set lxd/bridge-ipv4-dhcp-leases ${LXD_IPV4_DHCP_MAX}
    db_set lxd/bridge-ipv4-nat ${LXD_IPV4_NAT}

    if [ -n "${LXD_IPV6_ADDR}" ]; then
        db_set lxd/bridge-ipv6 true
    else
        db_set lxd/bridge-ipv6 false
    fi

    db_set lxd/bridge-ipv6-address ${LXD_IPV6_ADDR}
    db_set lxd/bridge-ipv6-netmask ${LXD_IPV6_MASK}
    db_set lxd/bridge-ipv6-nat ${LXD_IPV6_NAT}

    db_set lxd/bridge-dnsmasq ${LXD_CONFILE}
    db_set lxd/bridge-domain ${LXD_DOMAIN}
    db_set lxd/bridge-http-proxy ${LXD_IPV6_PROXY}
fi

# Ask questions
db_get lxd/setup-bridge
WAS_CONFIGURED="${RET}"

SEEN=false
if db_input medium lxd/setup-bridge; then
    SEEN=true
fi

db_go
db_get lxd/setup-bridge
if [ "${RET}" = "true" ]; then
    # Enable IPv4 and IPv6 on first manual run unless previously disabled
    if [ "${SEEN}" = "true" ]; then
        db_fget lxd/bridge-ipv4 seen
        if [ "${RET}" = "false" ]; then
            db_set lxd/bridge-ipv4 true
        fi

        db_fget lxd/bridge-ipv6 seen
        if [ "${RET}" = "false" ]; then
            db_set lxd/bridge-ipv6 true
        fi
    fi

    HAS_SUBNET=false

    db_input_not_empty medium lxd/bridge-name || true

    db_input medium lxd/bridge-ipv4 || true
    db_go
    db_get lxd/bridge-ipv4
    if [ "${RET}" = "true" ]; then
        # Pre-seed example values if none already set
        db_go
        db_get lxd/bridge-ipv4-address
        if [ -z "${RET}" ]; then
            db_input medium lxd/bridge-random-warning || true
            SUBNET=$(random_ipv4)
            db_set lxd/bridge-ipv4-address "${SUBNET}.1"
            db_set lxd/bridge-ipv4-netmask "24"
            db_set lxd/bridge-ipv4-dhcp-first "${SUBNET}.2"
            db_set lxd/bridge-ipv4-dhcp-last "${SUBNET}.254"
            db_set lxd/bridge-ipv4-dhcp-leases "252"
            db_set lxd/bridge-ipv4-nat true
        fi

        db_input_not_empty medium lxd/bridge-ipv4-address || true
        db_input_not_empty medium lxd/bridge-ipv4-netmask || true
        db_input_not_empty medium lxd/bridge-ipv4-dhcp-first || true
        db_input_not_empty medium lxd/bridge-ipv4-dhcp-last || true
        db_input_not_empty medium lxd/bridge-ipv4-dhcp-leases || true
        db_input medium lxd/bridge-ipv4-nat || true
        HAS_SUBNET=true
    else
        db_set lxd/bridge-ipv4-address ""
        db_set lxd/bridge-ipv4-netmask ""
        db_set lxd/bridge-ipv4-dhcp-first ""
        db_set lxd/bridge-ipv4-dhcp-last ""
        db_set lxd/bridge-ipv4-dhcp-leases ""
        db_set lxd/bridge-ipv4-nat true
    fi

    db_input medium lxd/bridge-ipv6 || true
    db_go
    db_get lxd/bridge-ipv6
    if [ "${RET}" = "true" ]; then
        # Pre-seed example values if none already set
        db_go
        db_get lxd/bridge-ipv6-address
        if [ -z "${RET}" ]; then
            db_input medium lxd/bridge-random-warning || true
            SUBNET=$(random_ipv6)
            db_set lxd/bridge-ipv6-address "${SUBNET}::1"
            db_set lxd/bridge-ipv6-netmask "64"
            db_set lxd/bridge-ipv6-nat true
        fi

        db_input_not_empty medium lxd/bridge-ipv6-address || true
        db_input_not_empty medium lxd/bridge-ipv6-netmask || true
        db_input medium lxd/bridge-ipv6-nat || true
        HAS_SUBNET=true
    else
        db_set lxd/bridge-ipv6-address ""
        db_set lxd/bridge-ipv6-netmask ""
        db_set lxd/bridge-ipv6-nat false
    fi

    db_input low lxd/bridge-dnsmasq || true
    db_input low lxd/bridge-domain || true

    if [ "${HAS_SUBNET}" = "true" ]; then
        db_set lxd/bridge-http-proxy false
    else
        db_set lxd/bridge-http-proxy true
    fi

    db_input low lxd/bridge-http-proxy || true
    db_input low lxd/update-profile || true
else
    db_input medium lxd/use-existing-bridge || true
    db_go
    db_get lxd/use-existing-bridge
    if [ "${RET}" = "true" ]; then
        if [ "${WAS_CONFIGURED}" = "true" ]; then
            db_set lxd/bridge-name ""
        fi

        db_input_not_empty medium lxd/bridge-name || true
        db_input low lxd/update-profile || true
    else
        db_set lxd/bridge-name ""
    fi
fi

db_go
