#!/bin/bash

# Configure the virtual environment that Gitlab provides for our CI jobs.
#
# This supports being used for either AWL or DAViCal. To test AWL we run
# the DAViCal regression tests as that is the best thing we have to exercise
# AWL currently.

set -e
set -x

davical_repo_path=$CI_PROJECT_DIR

mode=${1:-$CI_JOB_NAME}

ldap=0
memcache=0
interop=0

if [[ $mode =~ "ldap_memcache_auth" ]]; then
    ldap=1
    memcache=1
    memcache_auth=1
elif [[ $mode =~ "ldap" ]]; then
    ldap=1
    memcache=1
elif [[ $mode =~ "memcache_auth" ]]; then
    memcache=1
    memcache_auth=1
elif [[ $mode =~ "memcache" ]]; then
    memcache=1
elif [[ $mode =~ "interop" ]]; then
    interop=1
fi

# The images don't have man page directories?
mkdir -p /usr/share/man/man{0..10}

# When we install the davical deb, ignore libawl-php version dependency, as
# we also install the libawl-php .deb built by the AWL CI.
dpkg_ignore_depends="libawl-php"

# Images have no package info, load it.
apt-get -y update

###
### Pre-configure the locale so it is ready before other packages are
### installed.
###

apt-get -y install locales
echo "en_NZ.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
echo "LANG=en_NZ.UTF-8" > /etc/default/locale

###
### Install packages required for testing
###

packages="libdbd-pg-perl libyaml-perl postgresql-client postgresql
    curl xmlstarlet netcat-openbsd libtest-www-mechanize-perl
    libfile-pushd-perl libtemplate-perl libinline-files-perl
    libdigest-sha-perl sudo libfile-touch-perl"

if [[ $mode =~ "latestphp" ]]; then
    # PHP pgsql package is built from source, needs libpq-dev.
    packages="$packages libpq-dev"
else
    # The latestphp images already have some of these available, and others
    # need to installed in another method.
    packages="$packages libapache2-mod-php php php-cli php-pgsql php-xml
        php-curl"
fi

if [ $memcache == 1 ]; then
    packages="$packages php-memcached memcached"
fi

if [ $ldap == 1 ]; then
    packages="$packages php-ldap libnet-ldap-server-test-perl"
fi

if [ $interop == 1 ]; then
    packages="$packages composer phpunit"
fi

apt-get -y install $packages

###
### Setup PHP if we're using latestphp...
###

if [[ $mode =~ "latestphp" ]]; then
    # The image doesn't install PHP from debs, so ignore the dependencies.
    dpkg_ignore_depends="$dpkg_ignore_depends,php,php-pgsql,php-xml,php-cli"

    docker-php-ext-install -j$(nproc) pgsql
    docker-php-ext-install -j$(nproc) pdo_pgsql
    docker-php-ext-install -j$(nproc) calendar

    # The PHP 8.2 container has deflate enabled in Apache2, disable it.
    # This causes a test to fail because we're being sent a gzip compressed
    # result. My reading of the curl manpage says that it should be
    # decompressed by curl, but it isn't. Let's just disable the deflate
    # module.
    a2dismod -f deflate
fi

###
### Setup memcache if we're using it.
###

if [ $memcache == 1 ]; then
    phpenmod memcached
    /etc/init.d/memcached start

    conf_filter_memcache="| sed 's.//memcache ..g'"
fi

if [ $memcache_auth == 1 ]; then
    conf_filter_memcache="$conf_filter_memcache| sed 's.//memcache_auth ..g'"
fi

###
### Prepare PHP for LDAP if we're using it.
###

if [ $ldap == 1 ]; then
    phpenmod ldap

    conf_filter_ldap="| sed 's.//ldap ..g'"
fi

###
### If testing DAViCal, grab the git repo of AWL so we're using the latest
### code.
###

if [ -f davical.spec.in ]; then
    curl https://gitlab.com/davical-project/awl/-/archive/master/awl-master.tar.gz \
        | tar zxf -
    mv awl-master /usr/share/awl/
    chown -R www-data /usr/share/awl/
fi

###
### If testing AWL, grab the git repo of DAViCal for the tests we'll use.
###

if [ -f php-awl.spec.in ]; then
    curl https://gitlab.com/davical-project/davical/-/archive/master/davical-master.tar.gz \
        | tar zxf -
    ln -s . awl

    davical_repo_path="$CI_PROJECT_DIR/davical-master"

    ln -s /usr/share/davical $davical_repo_path
fi


###
### If testing DAViCal install the davical and libawl-php packages to test
###

if [ -f davical.spec.in ]; then
    dpkg --ignore-depends=$dpkg_ignore_depends -i *.deb
fi

mkdir -p /var/log/davical
chown www-data /var/log/davical

# Allow the testrunner user to write and read /var/log/davical .
# - Write for saving the output of some tests if they fail
chgrp adm /var/log/davical
chmod 775 /var/log/davical

###
### Setup DAViCal config files
###

# When testing DAViCal, the file already exists, when testing AWL the
# directory is missing.
rm -f /etc/davical/config.php
mkdir -p /etc/davical
eval cat $davical_repo_path/testing/regression-conf.php.example \
    \| sed 's.//\$c-\>dbg.\$c-\>dbg.' \
    $conf_filter_memcache \
    $conf_filter_ldap \
    > /etc/davical/regression-conf.php

for site in mycaldav mycaldav_ldap myempty; do
    ln -s /etc/davical/regression-conf.php /etc/davical/$site-conf.php
done

# We need to be able to restart apache as the regression user.
cp $davical_repo_path/testing/etc/sudoers /etc/sudoers.d/davical-tests

###
### Setup PostgreSQL
###

pg_ver=$(ls /etc/postgresql)
sed -i '/peer/d' /etc/postgresql/$pg_ver/main/pg_hba.conf
echo 'local  all  all  trust' >> /etc/postgresql/$pg_ver/main/pg_hba.conf
pg_ctlcluster $pg_ver main start
su postgres -c 'createuser davical_dba --createdb --createrole --superuser'
su postgres -c 'createuser davical_app --superuser'
su postgres -c 'createuser testrunner --superuser'
# Why? You don't need to restart PG after creating users.
#pg_ctlcluster $pg_ver main restart

###
### Setup testrunner user
###

useradd testrunner
# testrunner needs to be able to read /var/log/apache2/regression-error.log
# for the memcache tests.
adduser testrunner adm

# dav_test may need to write out temporary config files here.
chown -R testrunner $davical_repo_path/testing

###
### Configure Apache2
###

echo '127.0.1.1  regression mycaldav mycaldav_ldap myempty' >> /etc/hosts

rm /etc/apache2/ports.conf /etc/apache2/sites-enabled/000-default.conf \
    && touch /etc/apache2/ports.conf

cp $davical_repo_path/testing/apache-site.conf.example \
    /etc/apache2/sites-enabled/davical-regression.conf

if [ -f php-awl.spec.in ]; then
    sed -i "s,/path/to/awl,$CI_PROJECT_DIR,;
            s,/path/to/davical,$davical_repo_path," \
        /etc/apache2/sites-enabled/davical-regression.conf
else
    sed -i 's/\/path\/to/\/usr\/share/g' \
        /etc/apache2/sites-enabled/davical-regression.conf
fi

# We need to have some PHP files in a known place.
if [ ! -f php-awl.spec.in ]; then
    ln -s $davical_repo_path/testing /usr/share/davical/testing
fi


a2enmod rewrite
a2enmod headers
apache2ctl start

# Ensure that the jobs that need to drop in static files for Apache to serve
# up can do so.
mkdir -p /usr/share/davical/htdocs/testfiles
chown testrunner /usr/share/davical/htdocs/testfiles
ln -s /usr/share/davical/htdocs/testfiles $davical_repo_path/htdocs

###
### Set up for carddavclientinterop
###

if [ $interop == 1 ]; then
    cd $davical_repo_path
    curl https://codeload.github.com/mstilkerich/carddavclient/tar.gz/master | tar zxf -

    cd carddavclient-master
    composer install

    cat <<EOF > tests/Interop/AccountData.php
<?php

declare(strict_types=1);
namespace MStilkerich\Tests\CardDavClient\Interop;
use MStilkerich\CardDavClient\Account;
use MStilkerich\CardDavClient\AddressbookCollection;
use MStilkerich\CardDavClient\Config;

final class AccountData {
    public const ACCOUNTS = [
        "Davical" => [
            "username"     => "user3",
            "password"     => "user3",
            "discoveryUri" => "http://regression",
            "featureSet"   => TestInfrastructureSrv::SRVFEATS_DAVICAL,
            "syncAllowExtraChanges" => false,
        ],
    ];

    public const ADDRESSBOOKS = [
        "Davical_0" => [
            "account"     => "Davical",
            "url"         => "http://regression/caldav.php/user3/addresses/",
            "displayname" => "user3 addresses",
            "description" => null,
        ],
    ];
}
EOF

    mkdir -p testreports/interop
fi
