#!/bin/bash

export DISPLAY=:1

export REPOROOT="${REPOROOT:-$(git rev-parse --show-toplevel)}"

function run_tor {
    tor > /tmp/tor.out 2>&1 || cat /tmp/tor.out
}

function run_xvfb() {
    (setsid Xvfb :1 -screen 0 1024x768x24 -ac +extension GLX +render -noreset >& /tmp/xvfb.out || cat /tmp/xvfb.out) &

    # give it time to start
    for _ in {1..10}
    do
        xdpyinfo -display :1 >/dev/null 2>&1 && return 0
        sleep 1
    done
    xdpyinfo -display :1 >/dev/null 2>&1 || (echo "Xvfb is not available"; exit 1)
}

function run_redis() {
    rm -f "${REPOROOT}/securedrop/dump.rdb"
    redis_password=$(cd "${REPOROOT}/securedrop" && python -c "import rq_config; print(rq_config.REDIS_PASSWORD)")
    echo "$redis_password" > /tmp/redispasswd
    echo "requirepass ${redis_password}" | sudo -u redis tee -a /etc/redis/redis.conf
    echo "Starting redis..."
    sudo service redis-server start
}

function setup_vncauth {
    x11vnc -storepasswd freedom /tmp/vncpasswd
}

function run_x11vnc() {
    setsid x11vnc -display :1 -geometry 1024x768 -rfbauth /tmp/vncpasswd -rfbport 5909 -shared >& /tmp/x11vnc.out || cat /tmp/x11vnc.out
}

function urandom() {
    sudo rm /dev/random ||:
    sudo ln -s /dev/urandom /dev/random || echo "Unable to replace /dev/random"
}

function append_to_exit() {
    local existing
    existing="$(trap | sed -n "/EXIT\$/s/^trap -- '\(.*\)' EXIT/\1/p")"
    trap "${existing:-true} ; $1" EXIT
}

function maybe_create_config_py() {
    if ! test -f "${REPOROOT}/securedrop/config.py" ; then
        append_to_exit "rm ${REPOROOT}/securedrop/config.py"
        append_to_exit "rm ${REPOROOT}/securedrop/rq_config.py"
        (cd "$REPOROOT" && make test-config)
    fi
}

function maybe_use_tor() {
    if [[ -n "${USE_TOR:-}" ]]; then
        echo "Setting up Tor..."
        if [ ! -d "/var/lib/tor/services" ]; then
            sudo chown -R debian-tor:debian-tor /var/lib/tor/services
        else
            sudo -u debian-tor mkdir -p /var/lib/tor/services
        fi
        # append torrc lines for SI and JI
        echo "HiddenServiceDir /var/lib/tor/services/source/" | sudo tee -a /etc/tor/torrc
        echo "HiddenServicePort 80 127.0.0.1:8080" | sudo tee -a /etc/tor/torrc
        echo "HiddenServiceDir /var/lib/tor/services/journalist/" | sudo tee -a /etc/tor/torrc
        echo "HiddenServicePort 80 127.0.0.1:8081" | sudo tee -a /etc/tor/torrc
        # start Tor to create service directories
        sudo service tor start
        if sudo test -f "/var/lib/tor/services/journalist_auth_token.prv.pem"; then
            # recover x25519 key
            sudo cat /var/lib/tor/services/journalist_auth_token.prv.pem | tee /tmp/k1.prv.pem
        else
            echo "Generating new client authorization..."
            # create x25519 keypair and journalist client auth file
            openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
            # store private auth token for regeneration after restarts
            sudo cp /tmp/k1.prv.pem /var/lib/tor/services/journalist_auth_token.prv.pem
        fi
        grep -v " PRIVATE KEY" < /tmp/k1.prv.pem | base64pem -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.prv.key
        openssl pkey -in /tmp/k1.prv.pem -pubout | grep -v " PUBLIC KEY" | base64pem -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.pub.key
        echo "descriptor:x25519:$(cat /tmp/k1.pub.key)" | sudo -u debian-tor tee /var/lib/tor/services/journalist/authorized_clients/client.auth
        # shellcheck disable=SC2024
        sudo -u debian-tor cat /var/lib/tor/services/source/hostname > /var/lib/securedrop/source_v3_url
        # kill and restart Tor to pick up authorized_clients change
        # (restart a little flaky hence the kill)
        sudo kill "$(cat /run/tor/tor.pid)"; sudo service tor restart
        # print out the addresses and the JI client auth key

        si_address="$(sudo -u debian-tor cat /var/lib/tor/services/source/hostname)"
        ji_address="$(sudo -u debian-tor cat /var/lib/tor/services/journalist/hostname)"
        ji_authkey="$(sudo -u debian-tor cat /tmp/k1.prv.key)"
        sdkey_fpr="$(gpg --with-fingerprint --with-colons ./tests/files/test_journalist_key.pub | grep -e '^fpr' | tr -d 'fpr:')"

        cat > /tmp/qubes-config.json <<EOF
{
  "submission_key_fpr": "${sdkey_fpr}",
  "hidserv": {
    "hostname": "${ji_address}",
    "key": "${ji_authkey}"
  },
  "environment": "prod",
  "vmsizes": {
     "sd_app": 10,
     "sd_log": 5
  }
}
EOF
        echo
        echo "Tor configuration complete! details as follows:"
        echo "--------"
        echo "Source Interface:     http://${si_address}"
        echo "Journalist Interface: http://${ji_address}"
        echo "Journalist Auth Key:  ${ji_authkey}"
        echo "--------"
        echo
        echo "SecureDrop Workstation config.json:"
        echo "--------"
        cat /tmp/qubes-config.json
        echo "--------"
    fi
}

function reset_demo() {
    # Set up GPG keys directory structure.
    sudo mkdir -p /var/lib/securedrop/{store,keys,tmp}
    sudo chown -R "$(id -u)" /var/lib/securedrop
    cp ./tests/files/test_journalist_key.pub /var/lib/securedrop/journalist.pub
    gpg2 --homedir /var/lib/securedrop/keys --import /var/lib/securedrop/journalist.pub >& /tmp/gpg.out || cat /tmp/gpg.out

    # Create gpg-agent.conf
    echo allow-loopback-pinentry > /var/lib/securedrop/keys/gpg-agent.conf
    echo 'default-cache-ttl 0' >> /var/lib/securedrop/keys/gpg-agent.conf

    # Kill gpg-agent(s) if they exist so it picks up the new config on restart.
    pkill -f gpg-agent || true
    # Note that we should avoid `gpgconf --kill gpg-agent` since the pkill command will
    # handle killing multiple gpg-agent processes if they exist (this is what we want).

    # Set permissions on GPG-related directories/files.
    sudo chown -R "$(id -gn)" /var/lib/securedrop/keys
    chmod 700 /var/lib/securedrop/keys
    chmod 600 /var/lib/securedrop/keys/*

    # If the following directories exist, make sure they have the proper permissions.
    chmod -f 700 /var/lib/securedrop/keys/private-keys-v1.d || true
    chmod -f 700 /var/lib/securedrop/keys/openpgp-revocs.d || true

    # Compile translated strings
    pybabel compile --directory translations/

    # remove previously uploaded custom logos
    rm -f /var/www/securedrop/static/i/custom_logo.png

    # create an empty database
    sqlite3 /var/lib/securedrop/db.sqlite .databases &> /dev/null

    ./manage.py reset

    gpg2 --homedir /var/lib/securedrop/keys --no-default-keyring --keyring /var/lib/securedrop/keys/pubring.gpg --import /var/lib/securedrop/journalist.pub

    # Can't pass an array environment variable with "docker --env", so
    # break up the string we can pass.
    if [ -n "${LOADDATA_ARGS:-""}" ]
    then
        IFS=" " read -r -a loaddata_arg_array <<< "${LOADDATA_ARGS}"
        ./loaddata.py "${loaddata_arg_array[@]}"
    else
        ./loaddata.py
    fi
}

function build_redwood() {
    source /etc/os-release
    # For the demo, we build the wheel at container build time instead of
    # during launch, so skip this part
    if [[ -z "${SKIP_REDWOOD_BUILD:-}" ]]; then
        # Create a debug build of redwood and install it in the app-code virtualenv
        # TODO: add live reload support
        # We tell cargo to put its registry/crate cache and build cache in the target/ folder so
        # it persists instead of being recreated from scratch each time the container starts. The
        # cache needs to be split across OS versions because it can't tell that it's supposed to
        # link to a different libssl version.
        # n.b. we can't re-use the host's caches because of permission differences
        PATH="$PATH:/opt/cargo/bin/" \
        CARGO_HOME="${REPOROOT}/target/cargo-dev" \
            python3 "${REPOROOT}/redwood/build-wheel.py" --redwood "${REPOROOT}/redwood" --target "${REPOROOT}/target/dev-${VERSION_CODENAME}"
        /opt/venvs/securedrop-app-code/bin/pip install "${REPOROOT}"/redwood/redwood-*.whl
    fi
}
