#!/bin/bash

set -e

if [ ! -e "setup.py" ]; then
	echo "The script must be executed from within the repository's root directory."
	exit
fi

if [ -z "${SECRET_PEERINGDB_API_KEY}" ]; then
    echo "SECRET_PEERINGDB_API_KEY must be set, but it isn't."
    exit
fi

export PYTHONPATH="`pwd`"
ROOT="`pwd`"

DOCS_DIR="`pwd`/docs"
CFG_FILE="var/build_doc.yml"

OPTS="--cfg $CFG_FILE"
if [ "$DEBUG" == "1" ]; then
	OPTS="$OPTS --logging-level DEBUG"
fi

function publish_docs() {
	title "Publishing docs via HTTP"

	echo "cd $DOCS_DIR ; make html ; cd _build/html/ ; python3 -m http.server -b 127.0.0.1 8000 ; cd $ROOT"
	cd $DOCS_DIR
	make html
	cd _build/html/
	python3 -m http.server -b 127.0.0.1 8000
	cd $ROOT
}

function title() {
	echo "$(tput bold)$1$(tput sgr0)"
}

function filter() {
	if [ -n "$FILTER_EXAMPLE_ID" -a "$FILTER_EXAMPLE_ID" != "$1" ]; then
		title "SKIP $1 $2"
		return 1
	fi
	if [ -n "$FILTER_EXAMPLE_ARG1" -a "$FILTER_EXAMPLE_ARG1" != "$2" ]; then
		title "SKIP $1 $2"
		return 1
	fi
	return 0
}

if [ "$1" == "publish" ]; then
	publish_docs
	exit
fi

FILTER_EXAMPLE_ID=""
FILTER_EXAMPLE_ARG1=""
if [ -n "$1" ]; then
	FILTER_EXAMPLE_ID="$1"
	shift
fi
if [ -n "$1" ]; then
	FILTER_EXAMPLE_ARG1="$1"
	shift
fi

BIRD2_LATEST_VERSION=$(cat << EOF | python -
from pierky.arouteserver.builder import BIRDConfigBuilder
print([_ for _ in BIRDConfigBuilder.AVAILABLE_VERSION if _.startswith("2")][-1])
EOF
)
OPENBGPD_LATEST_VERSION=$(cat << EOF | python -
from pierky.arouteserver.builder import OpenBGPDConfigBuilder
print(OpenBGPDConfigBuilder.AVAILABLE_VERSION[-1])
EOF
)

# ----------------------------------------------------
D=docs/REJECT_REASON_COMMUNITIES.txt
cat << EOF > $D
.. DO NOT EDIT: this file is automatically created by ../utils/build_doc

Reject reasons
~~~~~~~~~~~~~~

  ===== =========================================================
     ID Reason
  ===== =========================================================
      0 Special meaning: the route must be treated as rejected. *

EOF
cat << EOF | python >> $D
from pierky.arouteserver.reject_reasons import REJECT_REASONS
for reason, description in REJECT_REASONS.items():
    print("{0:>7} {1}".format(reason, description))

EOF
cat << EOF >> $D

  65535 Unknown
  ===== =========================================================
EOF

# ----------------------------------------------------

title "Rendering GENERAL.rst from config.d/general.yml"
./utils/make_general.py

title "Generating examples configurations"

function RenderExample() {
	DST="$1" ; shift
	COMMAND="$1" ; shift
	GENERAL="$1" ; shift
	CLIENTS="$1" ; shift
	BOGONS="$1" ; shift

	filter "$DST" "$COMMAND" || return 0

	CMD="./scripts/arouteserver $COMMAND $OPTS --general $GENERAL --clients $CLIENTS --bogons $BOGONS"

	if [ "$COMMAND" == "bird" ]; then
		BIRD_VER="$1" ; shift
		if [ "$BIRD_VER" == "1" ]; then
			IP_VER="$1" ; shift
			$CMD --ip-ver $IP_VER -o examples/$DST/bird$IP_VER.conf --ignore-issues \* $@
		else
			$CMD --target-version ${BIRD2_LATEST_VERSION} --ignore-issues \* -o examples/$DST/bird_v2.conf $@
		fi
	elif [ "$COMMAND" == "openbgpd" ]; then
		$CMD -o examples/$DST/openbgpd.conf --ignore-issues \*
	elif [ "$COMMAND" == "html" ]; then
		$CMD -o examples/$DST/description.html
		cp examples/$DST/description.html $DOCS_DIR/_static/examples_$DST.html
	elif [ "$COMMAND" == "md" ]; then
		$CMD -o examples/$DST/description.md
		cp examples/$DST/description.md $DOCS_DIR/_static/examples_$DST.md
	elif [ "$COMMAND" == "template-context" ]; then
		if [ "$#" -gt 0 ]; then
			IP_VER="$1" ; shift
			IP_VER_OPT="--ip-ver $IP_VER"
		else
			IP_VER=""
			IP_VER_OPT=""
		fi
		$CMD $IP_VER_OPT -o examples/$DST/template-context$IP_VER
	elif [ "$COMMAND" == "irr-as-set" ]; then
		$CMD -o examples/$DST/irr-as-set.txt --template-file-name plain_rpsl.j2
		cp examples/$DST/irr-as-set.txt $DOCS_DIR/_static/examples_${DST}_irr-as-set.txt
	else
		echo "Command unknown: $COMMAND"
	fi
}

function RenderConfigureExample() {
	DAEMON="$1"; shift
	DST="$1"; shift
	ANSWERS="$1"; shift

	filter "configure" "$1" || return 0

	CMD="./scripts/arouteserver configure $OPTS --output examples/auto-config/${DST} --preset-answer $ANSWERS"

	[[ -e examples/auto-config/${DST} ]] && rm examples/auto-config/${DST}
	$CMD

	CMD="./scripts/arouteserver html $OPTS --output examples/auto-config/${DST}.html --general examples/auto-config/${DST}"

	$CMD &>/dev/null

	cp examples/auto-config/${DST}.html $DOCS_DIR/_static/examples_auto-config_${DST}.html

	CMD="./scripts/arouteserver md $OPTS --output examples/auto-config/${DST}.md --general examples/auto-config/${DST}"

	$CMD &>/dev/null

	cp examples/auto-config/${DST}.md $DOCS_DIR/_static/examples_auto-config_${DST}.md
}

function ClientsFromEuroIX() {
	URL="$1"; shift
	IXP_ID="$1"; shift
	OUTPUT_FILE="$1"; shift
	VLAN_ID="$1"; shift
	CMD="./scripts/arouteserver clients-from-euroix $OPTS --url $URL $IXP_ID -o $OUTPUT_FILE"
	if [ -n "$VLAN_ID" ]; then
		CMD="$CMD --vlan $VLAN_ID"
	fi

	$CMD

	./scripts/arouteserver bird $OPTS --test-only --general "config.d/general.yml" --clients $OUTPUT_FILE --bogons "config.d/bogons.yml" --ip-ver 4
	./scripts/arouteserver bird $OPTS --test-only --general "config.d/general.yml" --clients $OUTPUT_FILE --bogons "config.d/bogons.yml" --ip-ver 6
}

function IXFMemberExportFromClients() {
	CLIENTS="$1"; shift
	DST="$1"; shift

	./scripts/arouteserver ixf-member-export $OPTS --clients $CLIENTS --output $DST "Test IXP"
}

title "Building example: configure command output"

D="examples/auto-config/README.rst"
cat << EOF > $D
.. DO NOT EDIT: this file is automatically created by /utils/build_doc

\`\`configure\`\` command output
----------------------------

The \`\`configure\`\` command can be used to quickly generate policy definition files (*general.yml*) which are based on suggested settings and best practices.

A list of BGP communities is also automatically built.

.. code-block:: console

   $ arouteserver configure --output examples/auto-config/bird-general.yml
EOF

G="bird-general.yml"
RenderConfigureExample "bird" $G \
	"daemon=bird version=${BIRD2_LATEST_VERSION} asn=64496 router_id=192.0.2.1 black_list=192.0.2.0/24,2001:db8::/32" | \
		sed 's/^/   /' >> $D
./scripts/arouteserver bird $OPTS --target-ver ${BIRD2_LATEST_VERSION} --ip-ver 4 --general examples/auto-config/$G --clients config.d/clients.yml --test-only -o /dev/null

G="openbgpd-general.yml"
RenderConfigureExample "openbgpd" $G \
	"daemon=openbgpd version=${OPENBGPD_LATEST_VERSION} asn=64496 router_id=192.0.2.1 black_list=192.0.2.0/24,2001:db8::/32" &>/dev/null
./scripts/arouteserver openbgpd $OPTS --target-ver ${OPENBGPD_LATEST_VERSION} --general examples/auto-config/$G --clients config.d/clients.yml --test-only -o /dev/null

echo "The textual description (HTML and Markdown) generated on the basis of the *general.yml* files produced by this command is also reported here." >> $D

# Invalidating the cache because the previous commands fetched the real (huge)
# dataset from the RIPE RPKI Validator, while the following commands just need
# to used a very small subset of data for the sake of readability of the
# example configs that are going to build.
rm var/build_doc_cache/ripe-rpki-cache.json || true
rm var/cache/ripe-rpki-cache.json || true

title "Building example: default, BIRD, IPv4"
G="config.d/general.yml"
C="config.d/clients.yml"
RenderExample "default" "bird" "$G" "$C" "config.d/bogons.yml" 1 4

title "Building example: default, BIRD, IPv6"
RenderExample "default" "bird" "$G" "$C" "config.d/bogons.yml" 1 6

title "Building example: default, BIRD v2"
RenderExample "default" "bird" "$G" "$C" "config.d/bogons.yml" 2

title "Building example: default, OpenBGPD, IPv4 + IPv6"
RenderExample "default" "openbgpd" "$G" "$C" "config.d/bogons.yml"

title "Building example: default, Jinja2 template context"
RenderExample "default" "template-context" "$G" "$C" "config.d/bogons.yml" 4
RenderExample "default" "template-context" "$G" "$C" "config.d/bogons.yml" 6
RenderExample "default" "template-context" "$G" "$C" "config.d/bogons.yml"

title "Building example: default, HTML"
RenderExample "default" "html" "$G" "$C" "config.d/bogons.yml"
RenderExample "default" "md" "$G" "$C" "config.d/bogons.yml"

title "Building example: default, IRR AS-SET object"
RenderExample "default" "irr-as-set" "$G" "$C" "config.d/bogons.yml"

title "Building example: rich, BIRD, IPv4"
G="examples/rich/general.yml"
C="examples/rich/clients.yml"
RenderExample "rich" "bird" "$G" "$C" "config.d/bogons.yml" 1 4 --use-local-files client

title "Building example: rich, BIRD, IPv6"
RenderExample "rich" "bird" "$G" "$C" "config.d/bogons.yml" 1 6

title "Building example: rich, BIRD v2"
RenderExample "rich" "bird" "$G" "$C" "config.d/bogons.yml" 2

title "Building example: rich, OpenBGPD, IPv4 + IPv6"
RenderExample "rich" "openbgpd" "$G" "$C" "config.d/bogons.yml"

title "Building example: rich, Jinja2 template context"
RenderExample "rich" "template-context" "$G" "$C" "config.d/bogons.yml" 4
RenderExample "rich" "template-context" "$G" "$C" "config.d/bogons.yml" 6
RenderExample "rich" "template-context" "$G" "$C" "config.d/bogons.yml"

title "Building example: rich, HTML"
RenderExample "rich" "html" "$G" "$C" "config.d/bogons.yml"
RenderExample "rich" "md" "$G" "$C" "config.d/bogons.yml"

title "Building example: rich, IRR AS-SET object"
RenderExample "rich" "irr-as-set" "$G" "$C" "config.d/bogons.yml"

title "Building example: BIRD hooks"
G="examples/bird_hooks/general.yml"
C="examples/bird_hooks/clients.yml"
HOOKS="pre_receive_from_client post_receive_from_client pre_announce_to_client post_announce_to_client scrub_communities_in scrub_communities_out apply_blackhole_filtering_policy route_can_be_announced_to announce_rpki_invalid_to_client"
RenderExample "bird_hooks" "bird" "$G" "$C" "config.d/bogons.yml" 1 4 --use-hooks $HOOKS --use-local-files header
RenderExample "bird_hooks" "bird" "$G" "$C" "config.d/bogons.yml" 1 6 --use-hooks $HOOKS --use-local-files header

title "Building example: BIRD v2 and OpenBGPD RPKI RTR protocol"
G="examples/rpki_rtr/general.yml"
C="examples/rpki_rtr/clients.yml"
RenderExample "rpki_rtr" "bird" "$G" "$C" "config.d/bogons.yml" 2

title "Building example: auto-config via 'configure', BIRD"
C="config.d/clients.yml"
G="examples/auto-config/bird-general.yml"
RenderExample "auto-config" "bird" "$G" "$C" "config.d/bogons.yml" 1 4 --target-ver ${BIRD2_LATEST_VERSION}

title "Building example: auto-config via 'configure', OpenBGPD"
C="config.d/clients.yml"
G="examples/auto-config/openbgpd-general.yml"
RenderExample "auto-config" "openbgpd" "$G" "$C" "config.d/bogons.yml" --target-ver ${OPENBGPD_LATEST_VERSION}

title "Build clients from Euro-IX files? [yes/NO] "
read YES_NO

if [ "$YES_NO" == "yes" ]; then
	ClientsFromEuroIX "https://my.ams-ix.net/api/v1/members.json" 2 "examples/clients-from-euroix/amsix.yml" 502
	ClientsFromEuroIX "https://www.inex.ie/ixp/apiv1/member-list/list" 1 "examples/clients-from-euroix/inex.yml" 2
fi

title "Build IX-F Member Export files from clients? [yes/NO] "
read YES_NO

if [ "$YES_NO" == "yes" ]; then
	IXFMemberExportFromClients "tests/real/clients/bcix.yml" "examples/ixf-member-export/bcix.json"
	IXFMemberExportFromClients "tests/real/clients/gr-ix.yml" "examples/ixf-member-export/gr-ix.json"
fi

# ----------------------------------------------------

title "Building Live tests scenarios TOC"
DST_FILE="$DOCS_DIR/LIVETESTS_SCENARIOS.rst"
rm $DOCS_DIR/LIVETESTS_SCENARIOS_*.rst

echo ".. DO NOT EDIT: this file is automatically created by /utils/build_doc" > $DST_FILE
echo "" >> $DST_FILE
echo ".. toctree::" >> $DST_FILE
echo "   :maxdepth: 1" >> $DST_FILE
echo "" >> $DST_FILE

cd tests/live_tests/scenarios/
for d in */; do
	SCENARIO_NAME=`basename $d`
	if [ -e "$SCENARIO_NAME/README.rst" ]; then
		echo ".. include:: ../tests/live_tests/scenarios/$SCENARIO_NAME/README.rst" > $DOCS_DIR/LIVETESTS_SCENARIOS_$SCENARIO_NAME.rst
		echo "   LIVETESTS_SCENARIOS_$SCENARIO_NAME" >> $DST_FILE
	fi
done

cd $ROOT

# ----------------------------------------------------

title "Building the supported BGP speakers pages"

cd $ROOT
./utils/build_integration_tests_docs.py > ${DOCS_DIR}/SUPPORTED_SPEAKERS_CI.txt
./utils/build_supported_speakers_table.py > ${DOCS_DIR}/SUPPORTED_SPEAKERS_FEATURES.txt

# ----------------------------------------------------

title "Building HTML description for real tests configuration"
TMP_CLIENTS_FILE="`mktemp`"
cat > $TMP_CLIENTS_FILE << EOF
clients:
  - asn: 1
    ip: 1.1.1.1
EOF

./scripts/arouteserver html --cfg $CFG_FILE --logging-config-file config.d/log.ini --clients $TMP_CLIENTS_FILE --general tests/real/general.yml -o tests/real/general.html
cp tests/real/general.html $DOCS_DIR/_static/tests_real_general.html
cp tests/real/last $DOCS_DIR/_static/tests_real_results.last
rm $TMP_CLIENTS_FILE

DST_FILE="$DOCS_DIR/REALTESTS.rst"

echo ".. DO NOT EDIT: this file is automatically created by /utils/build_doc" > $DST_FILE
echo "" >> $DST_FILE
cat tests/real/README.rst >> $DST_FILE
echo "They are also reported below." >> $DST_FILE
echo "" >> $DST_FILE
echo ".. literalinclude:: _static/tests_real_results.last" >> $DST_FILE

cd $ROOT

# ----------------------------------------------------

title "Building examples"
DST_FILE="$DOCS_DIR/EXAMPLES.rst"
rm $DST_FILE

echo ".. DO NOT EDIT: this file is automatically created by /utils/build_doc" > $DST_FILE
echo "" >> $DST_FILE
echo "Examples of configurations" >> $DST_FILE
echo "==========================" >> $DST_FILE

cd examples
for d in default rich bird_hooks clients-from-euroix auto-config ixf-member-export rpki_rtr; do
	EXAMPLE_NAME="$d"
	if [ -e "$EXAMPLE_NAME/README.rst" ]; then
		echo "" >> $DST_FILE
		cat $d/README.rst >> $DST_FILE
		echo "" >> $DST_FILE
		echo "https://github.com/pierky/arouteserver/blob/master/examples/$EXAMPLE_NAME" >> $DST_FILE

		set +e
		html_cnt=`ls $d/*.html 2>/dev/null | wc -l`
		set -e
		if [ $html_cnt -eq 1 ]; then
			echo "" >> $DST_FILE
			echo "See the \`textual representation (HTML) of this configuration <_static/examples_$EXAMPLE_NAME.html>\`__." >> $DST_FILE
		elif [ $html_cnt -gt 1 ]; then
			for f in `ls $d/*.html`; do
				filename=`basename $f`
				echo "" >> $DST_FILE
				echo "$filename - See the \`textual representation (HTML) of this configuration <_static/examples_${EXAMPLE_NAME}_${filename}>\`__." >> $DST_FILE
			done
		fi
	fi
done

cd $ROOT

# ----------------------------------------------------

title "Building README.rst"
DST_FILE="README.rst"

echo ".. DO NOT EDIT: this file is automatically created by /utils/build_doc" > $DST_FILE
echo "" >> $DST_FILE
cat $DOCS_DIR/README_header.txt >> $DST_FILE
cat $DOCS_DIR/FEATURES.rst >> $DST_FILE
cat $DOCS_DIR/README_fulldocs.txt >> $DST_FILE
cat $DOCS_DIR/STATUS.txt >> $DST_FILE
cat $DOCS_DIR/README_footer.txt >> $DST_FILE

# ----------------------------------------------------

title "Testing package long description..."

python setup.py --long-description | rst2html.py - /dev/null --strict --syntax-highlight=none

# ----------------------------------------------------

publish_docs
