#!/bin/bash
# SPDX-License-Identifier: MIT

set -ex

SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $SELF_DIR/forgejo-lib.sh

: ${LOOPS:=80}
: ${LOOP_DELAY:=5}
WORKDIR=$(mktemp -d)
: ${DIR:=$(pwd)}

trap "rm -fr $WORKDIR" EXIT

function branch_tip() {
    local url="$1"
    local repo="$2"
    local branch="$3"

    forgejo.sh retry forgejo-curl.sh api_json $url/api/v1/repos/$repo/branches/$branch >& /dev/null
    forgejo-curl.sh api_json $url/api/v1/repos/$repo/branches/$branch |  jq --raw-output .commit.id
}

function get_status() {
    local url="$1"
    local repo="$2"
    local sha="$3"

    forgejo-curl.sh api_json $url/api/v1/repos/$repo/commits/$sha/status
}

function check_status() {
    local url="$1"
    local repo="$2"
    local sha="$3"
    local expected_status="$4"
    local expected_description="$5"

    get_status $url $repo $sha > /tmp/status.json
    local status="$(jq --raw-output .state < /tmp/status.json)"
    local description="$(jq --raw-output .statuses[0].description < /tmp/status.json)"
    if test "$status" = "$expected_status" && test -z "$expected_description" -o "$description" = "$expected_description"; then
	echo OK
    elif test "$status" = "failure" -o "$status" = "success"; then
	echo NOK
    else
	echo RETRY
    fi
}

function wait_success() {
    wait_status success "$@"
}

function wait_failure() {
    wait_status failure "$@"
}

function wait_running() {
    wait_status pending "$@" "Has started running"
}

function wait_status() {
    local status="$1"
    local url="$2"
    local repo="$3"
    local sha="$4"
    local description="$5"

    for i in $(seq $LOOPS); do
	if test $(check_status "$url" "$repo" "$sha" "$status" "$description") != RETRY ; then
	    break
	fi
	test "$FORGEJO_RUNNER_LOGS" && tail $FORGEJO_RUNNER_LOGS
	sleep $LOOP_DELAY
    done
    if test $(check_status "$url" "$repo" "$sha" "$status" "$description") != "OK" ; then
	get_status $url $repo $sha | jq .statuses
	test "$FORGEJO_RUNNER_LOGS" && cat $FORGEJO_RUNNER_LOGS
	return 1
    fi
}

function push() {
    local directory="$1"
    local url="$2"
    local owner="$3"
    local project="$4"
    local self_action="$5"
    local token="$6"

    local dir="$WORKDIR/$project"
    rsync -a --exclude .git $directory/ $dir/

    local workflows=$dir/.forgejo/workflows/*.yml
    if test "$(echo $workflows)" != "$workflows"; then
	sed -i \
            -e "s|SELF|$url/$owner/$self_action|g" \
	    -e "s|FORGEJO_TOKEN|$token|g" \
	    $dir/.forgejo/workflows/*.yml
    fi
    (
	cd $dir
	git init
	git checkout -b main
	git config user.email root@example.com
	git config user.name username
	git add .
	git commit -m 'initial commit'
	git remote add origin $url/$owner/$project
	git push --force -u origin main
	sha=$(git rev-parse HEAD)
	echo $sha > SHA
    )
}

function push_workflow() {
    local directory="$1"
    local url="$2"
    local owner="$3"
    local project="$4"
    local self_action="$5"
    local token="$6"

    if test -z "$token"; then
	echo missing token argument
	return 1
    fi

    push "$directory" "$url" "$owner" "$project" "$self_action" "$token"
}

function run_workflow() {
    local directory="$1"
    local url="$2"
    local owner="$3"
    local project="$4"
    local self_action="$5"
    local token="$6"

    push_workflow "$directory" "$url" "$owner" "$project" "$self_action" "$token"
    wait_success "$url" "$owner/$project" $(cat $WORKDIR/$project/SHA)
}

function clear_runner_cache() {
    if test -f $DIR/forgejo-runner-home ; then
	rm -fr $(cat $DIR/forgejo-runner-home)/.cache/act
    fi
}

function push_self_action() {
    local url="$1"
    local owner="$2"
    local self_action="$3"
    local tag="$4"

    clear_runner_cache

    local dir="$WORKDIR/self"
    git diff --exit-code
    git clone . $dir
    (
	cd $dir
	rm -fr .forgejo .git
	git init
	git checkout -b main
	git remote add origin "$url/$owner/$self_action"
	git config user.email root@example.com
	git config user.name username
	git add .
	git commit -m 'initial commit'
	git push --force origin main
	git tag --force $tag HEAD
	git push --force origin $tag
    )
}

function dependencies() {
    if ! which jq curl > /dev/null ; then
	apt-get -qq install -y jq curl
    fi
}

dependencies

"$@"