#! /bin/zsh -euf

# todo: if on `main' ignore, or patch reprepro!

# bug: -r but 'release' (changelog should mention it!)


source /usr/share/build-system/functions.sh
# set -x cannot be done in a functions?
eval $(possibly_trace)
check_getopt

check_start_gnupg

function usage()
{
    setopt POSIX_ARGZERO
    cat <<EOF
usage: ${0##*/} [options]

DESCRIPTION:
invoke gbp to create Debian binary package, from a git repository.

- git tag ... "distro/version" only on success.
- upload (where) ... dput-target ... taken from MBS_TARGETS env variable
- install (possibly) on HOST

OPTIONS:
[+-a arch] [-m] [-p dput-target]* [-v version ] [-s] [-o]

General:
-b --ignore  ... ignore Git branch
-f --force ... regenerate & commit even if apparently debian/changelog ...
-q --quiet ... use the generated commit msg without editing in an editor

-m --minor  ... increase the version only by minor step. Hint: semantics/changelog
--tag  [name]  default  {distro}/
-i --install ...
-o --auto  ... don't open the Editor -- Changelog is unverified.    DANGEROUS?
-h --help

-G  just push to GitHub

Packaging:
-s --source  ... build the tarball/source package too.
-u         don't sign

-p, --dput  [target] ... add named tput target.

Build environment:
-r, --distro [distro]		package for that distribution (default host one), ignore debian/changelog?
-a, --arch   architecture       default Host.

EOF
    unsetopt POSIX_ARGZERO
}

#### Setup defaults & initial state:

# We need to invoke dch, and then somehow debuild.
# So start collecting options for those:
typeset -a DEBUILD_OPTIONS
typeset -a DCH_OPTIONS
DEBUILD_OPTIONS=()
DCH_OPTIONS=()


# I have special make
DEBUILD_OPTIONS+=(-eMAKEFLAGS -eGITSHA)

DEBUG=y

# where does it come from? $DEB_BUILD_ARCH
ARCH=""
# Defaults for options:
USER_DISTRIBUTION=""
DISTRIBUTION=""

step=minor
build_source=no
FORCE=n
QUIET=n

# this is for the (pre/post) hooks .. for `dput-install'
POSTBUILD_INSTALL_OPTIONS="-I"

## Dput
# same what I use in zlogin for MBS_TARGETS!
typeset -T DPUT_TARGETS dput_targets :
dput_targets=()

typeset -a GBP_OPTIONS
GBP_OPTIONS=()

pre_build_hook=(pre-build-hook)

if ! my_own_project || [[ $(git branch --show-current) = main ]]
# This scans the control/control:
then
    DCH_OPTIONS+=("--ignore-branch")
    GBP_OPTIONS+=("--git-ignore-branch")
fi

just_push_to_github=0

### process command line:

# must be in the same order? no!
cmd_options=$(getopt --name $0 --shell bash \
    --longoptions help,arch,dput,ignore,install,noinstall,tag,version:,nocheck \
    --longoptions force,quiet,source,distro:,minor,major,github \
    --options ha:bfGr:T:p:qiIv:ousmM \
    -- "$@" ) || { usage && exit 1 }
eval set -- "$cmd_options"

while (( $# > 0 )) do
      case $1 in
          --help | -h)
              usage
              exit 0
              ;;
          --arch | -a)
              shift
              ARCH="$1"
              ;;
          --ignore | -b)
              DCH_OPTIONS+=("--ignore-branch")
              GBP_OPTIONS+=("--git-ignore-branch")
              ;;
          --force | -f)
              FORCE=y
              ;;
          --quiet | -q)
              QUIET=y
              ;;
          --dput | -p)
              shift
              dput_targets+=($1)
              ;;
          --github | -G )
              just_push_to_github=1
              ;;
          --distro | -r)
              shift
              USER_DISTRIBUTION="$1"
              ;;
          --tag | -T )
              shift
              git_tag=$1
              ;;
          --source | -s)
              # still  dpkg-buildpackage will call dpkg-source --before-build
              # which does not do harm, though.
              build_source=yes
              ;;
          ##  which is?  install the package?
          --install | -i)
              # fixme:
              GBP_OPTIONS+=("-i")
              ;;
          --install | -i)
              POSTBUILD_INSTALL_OPTIONS="-i"
              ;;
          --upgrade | -I)
              POSTBUILD_INSTALL_OPTIONS="-I"
              ;;
          --noinstall | +n)
              POSTBUILD_INSTALL_OPTIONS="-n"
              ;;

          --auto | -o)
              # non-interactive/offline
              DCH_OPTIONS+=("--spawn-editor=snapshot")
              ;;
          --minor | -m)
              step=minor
              ;;
          --major | -M)
              step=major
              ;;
          --version | -v)
              shift
              USER_VERSION=$1
              ;;
          -u)
              # don't sign??
              GBP_OPTIONS+=("-us"  "-uc")
              ;;
          --nocheck )
              DEB_BUILD_OPTIONS+=nocheck
              export DEB_BUILD_OPTIONS
              ;;
      esac
      shift
done

# No source package -> optimize
if [ $build_source != yes ]; then
    if [ $DEBUG = y ]; then info "Not building source package";fi
    GBP_OPTIONS+=(--git-no-create-orig)
fi

#todo: I could build arch-dependent & independent separately.
# -A build.
# for more architectures: -B builds.



## Check all data is ready/consistent. (Before invoking manual interaction).
# fallback on env-var value:
if [ "$dput_targets" = "" ]; then
    if [ $DEBUG = y ]; then info "checking fallback dput targets from Env";fi
    if [ -z "${MBS_TARGETS-}" ];
    then
        cecho red "No targets, only local then"
        exit 1
    else
        # fixme: since it comes from a generic shell, divide it as such:
        #dput_targets=${=MBS_TARGETS}
        DPUT_TARGETS=${MBS_TARGETS}
    fi
fi


## Prepare for the debian/changelog entry:
if [ "$DISTRIBUTION" = "" ]; then
    if [ $DEBUG = y ]; then info "guessing distribution";fi
    # todo:
    # when archi  ALL -> release
    # otherwise   lsb_release --short --codename
    DISTRIBUTION=${MBS_DISTRO:-release}
fi



## Decide how to build -- containers:
artifacts_dir=/gbp


## I want to be able to repeat the run.
# So, update the changelog and git tag only if needed.

## get the current version string.
if [ $DEBUG = y ]; then info "seeing if new changelog needs to be done";fi

# todo:
# if no debian/changelog or not in Git ->
#  --create

# if status OR not updated!
if changelog_needs_new_section "release"
then
    cecho red "Taking hint on VERSION from the debian/changelog"
    load_distr_version_from_changelog
    # drop_verbal_suffix

    # invokes: gbp dch
    if [[ $QUIET == y ]]; then
        generate_commit_changelog -q $step
    else
        generate_commit_changelog  $step
    fi
fi


# This must be done AFTER creating the "release" commit!
GITSHA=$(git rev-list --max-count=1 HEAD)
export GITSHA

calculate_for_distro()
{
    local distribution=$1

    local debspawn_config_toml=~/config/debspawn/debspawn-$distribution.toml

    # output:

    # DCH_OPTIONS+=("--git-dist=$USER_DISTRIBUTION")

    # note: all this is one argument!
    GBP_OPTIONS+=("--git-builder=debspawn --config $debspawn_config_toml build --only binary --buildflags=-b $distribution --setenv GITSHA=$GITSHA --setenv MAKEFLAGS=$MAKEFLAGS")
    artifacts_dir=/gbp/$distribution
}


if [[ $just_push_to_github == 1 ]]
then
    # update/reload:
    load_distr_version_from_changelog
    tag="$DISTRIBUTION/$VERSION"
    echo "Creating tag $tag" >&2
    # bug:  2:version is invalid tag!
    : ${tag::=${tag/:/_}}
    set -x
    if [[ -z $(git rev-parse --tags="$tag*" 2> /dev/null) ]]
    then

        if [[ -z $(git-sum) && -z $(git-segment) ]]
        then
            git tag -m 'release' $tag HEAD
        else
            # todo: the whole graph or from the current branch?
            # fixme:  sid/ not unstable/ ?
            git-store-hierarchy -t $tag $(git rev-parse HEAD)
            # git branch --show-current
            ## git-store-hierarchy -t unstable/1.31.2-1-maruska mmc-all

        fi
    fi

    # remote name:
    post-tag-hook
    # git push github $tag
    # open in browser?
    (set -x
     gh workflow list
    )
    exit 0
fi


if [[ -n "$USER_DISTRIBUTION" ]]; then
    GBP_OPTIONS+=("--git-dist=$USER_DISTRIBUTION")
    calculate_for_distro $USER_DISTRIBUTION
    # Skip installing build-dep by gbp:
    pre_build_hook+=(-s)
else
    # I still want to use debspawn:
    if false; then
        dpkg_buildpackage_flags=(--no-pre-clean)
        dpkg_buildpackage_flags+=(-b)
        GBP_OPTIONS+=("--git-builder=debuild $DEBUILD_OPTIONS $dpkg_buildpackage_flags")
    else
        # host_distro=sid
        calculate_for_distro sid
        # Skip installing build-dep by gbp:
        pre_build_hook+=(-s)
        # but changelog should list: unstable
    fi
fi


if [ $DEBUG = y ]; then info "Deciding for the Git tag";fi

# note: a tag is created by dput-install
# so this will not run, since gbp is unaware of the tag!
TAGOPTIONS=(--git-posttag=post-tag-hook)


echo exporting DPUT_TARGETS $DPUT_TARGETS
export DPUT_TARGETS

name=$(deb-pkg-name debian/control)
version=$(deb-pkg-version debian/changelog)
host_architecture=$(dpkg-architecture -q DEB_HOST_ARCH)


## What do do with the artifacts:
# fixme:
version=${version#*:}
changesfile="$artifacts_dir/${name}_${version}_${host_architecture}.changes"

if [ "$ARCH" != "" ]; then
    dpkg_buildpackage_flags+=(-B)
    # this receives all args from gbp buildpackage  unless --git- prefix.
    changesfile="$artifacts_dir/${name+$name-}$ARCH.changes"
    BUILDER="nspawn-debuild -a $ARCH -n $changesfile -- $DEBUILD_OPTIONS $dpkg_buildpackage_flags"
    export DEB_HOST_ARCH=$ARCH
    pre_build_hook+=(-a $ARCH)

    POSTBUILD="dput-install -r -n $changesfile"
elif [[ -n "$USER_DISTRIBUTION" ]]
then
    # do not install
    POSTBUILD="dput-install -r -n $changesfile"
else
    POSTBUILD="dput-install -r $POSTBUILD_INSTALL_OPTIONS $changesfile"
fi

# -sa dpkg-genchanges: force inclusion of original sources (in the changes file)

# set PREVERSION_HOOK_NAME
prepare_hook_name

args=(
    --git-ignore-new
    --git-cleaner=/bin/true
    # this could be inside the container, partly
    $PREVERSION_HOOK_NAME="$pre_build_hook"
    # this inside the container:
    --git-postbuild="$POSTBUILD"
    $TAGOPTIONS
    $GBP_OPTIONS
    # repeated!
    # -b
)

set -x
# note: additional options come from ~/.gbp.conf
gbp buildpackage $args
