#!/bin/bash

TRIGGER_COPR_CONFIG=${TRIGGER_COPR_CONFIG:-}
TRIGGER_COPR_PKGNAME=${TRIGGER_COPR_PKGNAME:-}

warn() {
    echo "$1" >&2
}

die() {
    warn "fatal: $1"
    exit 3
}

usage() {
    warn "usage: $0 [options] MODE"
    warn ""
    warn "Options:"
    warn ""
    warn "  -b BRN  build from branch BRN (default: last tag)"
    warn "  -c COPR_PROJECT  COPR project name"
    warn "  -C CONF   config file"
    warn "  -n      dry mode, don't do anything (just show"
    warn "          what would be done)"
    warn "  -r REL  use REL as Release number in SPEC file"
    warn "  -v VER  use VER as Version number in SPEC file"
    warn "  -u URL  use URL as base (to get last tag and"
    warn "          compose Source0 in SPEC file)"
    warn ""
    warn "If -b is not used, build is launched from last tag available"
    warn "in the GitHub repo.  In that case, Release is '1' and Version"
    warn "is deduced from the tag by removing the initial 'v'."
    warn ""
    warn "If -b is used, the project repo is temporarily cloned, and"
    warn "both Version and Release are found by consulting git-describe"
    warn "on the specified branch."
    warn ""
    warn "If MODE is 'scratch' (default), Release is pre-fixed by string"
    warn "'0.scratch.' and build is triggered in scratch COPR project."
    exit 2
}

last_version() {
    git ls-remote --tag "$UrlBase" \
      | grep '/tags/' \
      | cut -d/ -f3 \
      | grep -v '[^0-9a-z.]' \
      | sort -V \
      | tail -1 \
      | sed "s/^v//"
}

mkspec() {
    local self_version
    local cl_date
    self_version="$(basename "$0") $(git describe --tags)"
    cl_date=$(LC_ALL=C date +"%a %b %d %Y")
    sed -e "
        s|__APP_VERSION__|$Version|
        s|__APP_RELEASE__|$Release|
        s|__APP_URLBASE__|$UrlBase|
        s|__APP_BUILDSCRIPT_VERSION__|$self_version|
        s|__APP_DATE__|$cl_date|
    " <"$PkgName.spec.in"
}

git_guess() {
    #
    # Print git-guessed $1
    #
    local what=$1   # what we want (ver|rel)
    local describe  # full git-describe output
    local xtra=     # extra part (-N-gHASH)
    local num=0     # num. of commits since tag (N)
    local sha=      # '.g'+sha1 of this commit (gHASH)
    describe=$(git describe --tags --always HEAD)
    case $describe in
        *-*)                        #     v1.2.3-21-g654cba
            tag=${describe%%-*}     # tag=v1.2.3
            xtra=${describe#$tag-}  # xtra=-21-g654cba
            num=${xtra%%-*}         # num=21
            sha=.${xtra#$num-}      # sha=.g654cba
            ;;
        *)
            tag=$describe
            ;;
    esac
    case $what in
        ver)    echo "${tag#v}"         ;;
        rel)    echo "$((num + 1))$sha" ;;
    esac
}

choose_relpfx() {
    #
    # Choose COPR project based on $Mode
    #
    test "$Mode" == scratch && echo 0.scratch.
    return 0
}

read_conffile() {
    #
    # Read item T
    #
    local what=$1
    local fieldn
    case $what in
        urlbase) fieldn=2 ;;
        copr)    fieldn=3 ;;
    esac
    grep -v '^[[:blank:]]*#' "$ConfFile" \
      | grep "^ *$Mode\>" \
      | sed 's/  */ /g' \
      | cut -d' ' -f$fieldn
}

choose_conffile() {
    #
    # Find config file and echo its name
    #
    find . -name '*.trigger' \
      | cut -d/ -f2 \
      | grep .
}

do_action() {
    local url
    case $Action in
        build)
            copr build "$CoprProject" "$Tmp/$PkgName.spec"
            printf '\a'
            ;;
        demo)
            warn "demo mode active, we would build:"
            warn "    at $CoprProject"
            test -n "$Branch" && warn "    using branch $Branch"
            test -n "$Branch" || warn "    using last tag"
            warn "    from $UrlBase"
            warn "    yielding $PkgName-$Version-$Release.*.rpm"
            warn ""
            warn "===== BEGIN $PkgName.spec ====="
            cat "$Tmp/$PkgName.spec"
            warn "===== END $PkgName.spec ====="
            return 1
            ;;
        mkspec)
            cat "$Tmp/$PkgName.spec"
            ;;
        rpmstuff)
            url=$(
                grep -o 'Source.*:.*http.*' "$Tmp/$PkgName.spec" \
                  | sed "
                        s/.*http/http/
                        s/ *$//
                        s/%{version}/$Version/
                    "
            )
            wget --quiet "$url"
            cat "$Tmp/$PkgName.spec" > "$PkgName.spec"
            ;;
    esac
}

main() {
    local Version       # Version in SPEC file
    local Release       # Release in SPEC file
    local CoprProject   # COPR project
    local UrlBase       # GitHub URL base
    local Tmp           # our temp
    local Branch        # branch to use, if empty, tags are considered
    local Mode=scratch  # implies COPR project and release prefix
    local Action=build  # what to do
    local ConfFile      # config file to use
    local PkgName       # package name
    local es=0          # exit status
    which copr >/dev/null \
     || die "copr not found, try 'sudo install copr-cli'"
    Tmp=$(mktemp -d)
    while true; do case $1 in
        -C) ConfFile=$2;    shift 2 || usage ;;
        -a) Action=$2;      shift 2 || usage ;;
        -b) Branch=$2;      shift 2 || usage ;;
        -c) CoprProject=$2; shift 2 || usage ;;
        -u) UrlBase=$2;     shift 2 || usage ;;
        -r) Release=$2;     shift 2 || usage ;;
        -v) Version=${2#v}; shift 2 || usage ;;
        -n) Action=demo;    shift ;;
        -*) usage ;;
        *)  break ;;
    esac done
    Mode=${1:-$Mode}
    case $Action in
        build|demo|mkspec|rpmstuff) : ;;
        *) usage ;;
    esac
    test -n "$ConfFile" || ConfFile=$TRIGGER_COPR_CONFIG
    test -n "$ConfFile" || ConfFile=$(choose_conffile)
    test -n "$ConfFile" || die "could not find config file"
    test -r "$ConfFile" || die "could not read config file"
    test -n "$PkgName"  || PkgName=$TRIGGER_COPR_PKGNAME
    test -n "$PkgName"  || PkgName=${ConfFile%.trigger}
    test -n "$CoprProject" || CoprProject=$(read_conffile copr)
    test -n "$UrlBase"     || UrlBase=$(read_conffile urlbase)
    if test -n "$Branch"; then
        die "not implemented"
        test -n "$Version" || Version=$(git_guess ver)
        test -n "$Release" || Release=$(git_guess rel)
    else
        test -n "$Version" || Version=$(last_version)
        test -n "$Release" || Release=1
    fi
    Release=$(choose_relpfx)$Release
    mkspec >"$Tmp/$PkgName.spec"
        do_action
    rm -rf "$Tmp"
    return $es
}

main "$@"